Prev: Java work from home. Remote (telecommuting) jobs in Java.
Next: Zip question: Where are all the extra characters coming fromupon unzipping?
From: Marcin Rzeźnicki on 19 Oct 2009 08:43 On 19 Pa¼, 14:19, Marcin Rze¼nicki <marcin.rzezni...(a)gmail.com> wrote: > On 19 Pa¼, 13:08, Tomas Mikula <tomas.mik...(a)gmail.com> wrote: > > > > Example with generics can easily be substituted by some kind of > > > "trait" parameter > > > Sorry, I don't know what you mean by "trait" parameter? Do you mean that > > I would call the zero() method on some instance? > > Like myDummyVector.zero()? > > I borrowed the terminology from C++. More or less, you add type > parameter (let's say <Zero extends ZeroVector>) which has a method > like getZeroVector() (strictly speaking ZeroVector has this method). > Actual type parameter provides concrete implementation. > I forgot to clarify - you are right, all in all you call zero() method on some instance :-)
From: Tomas Mikula on 19 Oct 2009 09:06 On Oct 19, 2:19 pm, Marcin Rze¼nicki <marcin.rzezni...(a)gmail.com> wrote: > On 19 Pa¼, 13:08, Tomas Mikula <tomas.mik...(a)gmail.com> wrote: > > > > > On Sun, 18 Oct 2009 19:58:43 -0700, Marcin Rze¼nicki wrote: > > > On 19 Pa¼, 04:06, Tomas Mikula <tomas.mik...(a)gmail.com> wrote: > > >> I have searched this group for "abstract static methods" and found a > > >> couple of threads, but I think none of them was discussing the kind of > > >> semantics I am going to describe. As you might have guessed, I believe > > >> it would be useful :). I further believe it is fully complatible with > > >> the current language, but there might be caveats I have overlooked. I'm > > >> wonder if you would find it as useful as I do and if you see any > > >> problems with it. I know it is a long post and some parts may be > > >> difficult to understand. Therefore I will be thankful if you can read > > >> it all and think about it. > > > > Hi, > > > Interesting but I doubt it is going to be useful. First of all, because > > > statics should remain non-inheritable, static abstract actually forces > > > each subclass to implement its own definition - extreme nuisance in my > > > opinion. > > > Yes (unless the subclass is abstract). I think in some cases it is > > reasonable (as with the enforced no-arg constructor in Serializable, or > > some other serialization static methods. For example, if I want to > > deserialize an immutable object, I need to do it by a static method or a > > special constructor, because the non-static readObject(...) method in > > Java's serialization API is a mutator method. In my opinion it is > > reasonable to enforce own implementation of a (de)serialization method).. > > Hi, possibly it is reasonable, but what is wrong with how it is done > today (readObject/writeObject) which you are not required to implement > if default behavior suffices? I'm saying it is wrong, but just don't like that the implementation requires a lot of reflection. (I don't mind that implementation of statndard Java API requires reflection, because someone has already implemented it for me. But if I want to create my own serialization framework (e.g. for xml serialization), I need to do a lot of reflection which could be automated.) Probably one thing I find wrong with readObject - as I already mentioned, it prevents the object to be immutable. Though this could also be solved by declaring it static and use reflection. > > > > Example with generics can easily be substituted by some kind of > > > "trait" parameter > > > Sorry, I don't know what you mean by "trait" parameter? Do you mean that > > I would call the zero() method on some instance? > > Like myDummyVector.zero()? > > I borrowed the terminology from C++. More or less, you add type > parameter (let's say <Zero extends ZeroVector>) which has a method > like getZeroVector() (strictly speaking ZeroVector has this method). > Actual type parameter provides concrete implementation. I don't see how this would help. Would I call Zero.getZeroVector()? Probably you meant something else because this leads to the same problem with calling static method getZeroVector() on a type parameter. Could you provide an example? > > > or suitable simple design pattern (for example > > > Factory), or even with classic sub-typing (zero vector needs not know > > > its dimension, it can simply 'answer' with neutral element of the ring > > > on which it is constructed for each and every component query), > > > Allowing operations between a concrete vector and this general zero > > vector would require to also allow operations between 2D and 3D vetors - > > the original type safety would disappear. > > I don't get it, could you provide an example? If I understood well, you meant something like this: Class Vector { public static Vector getZeroVector(){ return someSpecialZeroVectorInstance; } public abstract Vector add(Vector v); } Class Vector2D { public Vector add(Vector v){...} ... } class MyClass<V extends Vector> { ... V v; // V is some concrete class, such as Vector2D ... Vector zero = Vector.getZeroVector(); v.add(zero); // adding a general Vector zero to concrete v // if this is allowed, then also the following is v.add(new Vector3D(1,2,3)); // summing 2D and 3D vector ... } > > > no big > > > win here either (eliminating type erasure is extremely welcome but for > > > other reasons). One big advantage of inheritance is, in my opinion, that > > > it enables you to compose more specialized classes from generic ones, it > > > is easy to imagine algebraic ordering relation between types based on > > > inheritance. Your version of statics breaks this assumption without > > > promise of any reward in exchange. > > > I don't see how it breaks this relation between classes. Also now it is > > possible to hide supertype's static methods by own implementation. I > > would only add that in some cases this hiding would be required. > > I was not very clear, it was late when I was writing :-) I guess what > I was trying to say was that you can impose ordering based on > specialization (as opposed to parent-child relationship). Each class > in an inheritance chain either extends or redefines partially its > ancestor (I am using 'or' as logical or). Therefore each class is > either more specialized (if redefinition occurs and it accepts > stronger contract, as in Rectangle->Square) or equally specialized (if > extension occurs and all redefinitions do not change contract - I > treat extension as an interface extension so that class can be used > _additionally_ in different context). Your proposal forces implementor > to provide implementation for non-inheritable method, so it really > can't take any benefit from redefinitions up the chain. Therefore all > concrete classes are at most equally specialized as their context of > usage is determined by a static method. So it does not play well with > most "inheritance patterns". That's how I see it. Now I don't get it. Can you provide an example where you have a class and its specialized subclass and adding an abstract static method to their interface removes/prohibits this specialization?
From: Marcin Rzeźnicki on 19 Oct 2009 09:51 On 19 Pa¼, 15:06, Tomas Mikula <tomas.mik...(a)gmail.com> wrote: > On Oct 19, 2:19 pm, Marcin Rze 1/4 nicki <marcin.rzezni...(a)gmail.com> > wrote: > > > > > On 19 Pa 1/4, 13:08, Tomas Mikula <tomas.mik...(a)gmail.com> wrote: > > > > On Sun, 18 Oct 2009 19:58:43 -0700, Marcin Rze 1/4 nicki wrote: > > > > On 19 Pa 1/4, 04:06, Tomas Mikula <tomas.mik...(a)gmail.com> wrote: > > > >> I have searched this group for "abstract static methods" and found a > > > >> couple of threads, but I think none of them was discussing the kind of > > > >> semantics I am going to describe. As you might have guessed, I believe > > > >> it would be useful :). I further believe it is fully complatible with > > > >> the current language, but there might be caveats I have overlooked.. I'm > > > >> wonder if you would find it as useful as I do and if you see any > > > >> problems with it. I know it is a long post and some parts may be > > > >> difficult to understand. Therefore I will be thankful if you can read > > > >> it all and think about it. > > > > > Hi, > > > > Interesting but I doubt it is going to be useful. First of all, because > > > > statics should remain non-inheritable, static abstract actually forces > > > > each subclass to implement its own definition - extreme nuisance in my > > > > opinion. > > > > Yes (unless the subclass is abstract). I think in some cases it is > > > reasonable (as with the enforced no-arg constructor in Serializable, or > > > some other serialization static methods. For example, if I want to > > > deserialize an immutable object, I need to do it by a static method or a > > > special constructor, because the non-static readObject(...) method in > > > Java's serialization API is a mutator method. In my opinion it is > > > reasonable to enforce own implementation of a (de)serialization method). > > > Hi, possibly it is reasonable, but what is wrong with how it is done > > today (readObject/writeObject) which you are not required to implement > > if default behavior suffices? > > I'm saying it is wrong, but just don't like that the implementation > requires a lot of reflection. (I don't mind that implementation of > statndard Java API requires reflection, because someone has already > implemented it for me. But if I want to create my own serialization > framework (e.g. for xml serialization), I need to do a lot of > reflection which could be automated.) Probably one thing I find wrong > with readObject - as I already mentioned, it prevents the object to be > immutable. Though this could also be solved by declaring it static and > use reflection. > > Yes, but someone did it for you either - JAXB, xStreams etc. This is not a type of work you do day-in day-out, so benefits are rarely to be seen > > > > > Example with generics can easily be substituted by some kind of > > > > "trait" parameter > > > > Sorry, I don't know what you mean by "trait" parameter? Do you mean that > > > I would call the zero() method on some instance? > > > Like myDummyVector.zero()? > > > I borrowed the terminology from C++. More or less, you add type > > parameter (let's say <Zero extends ZeroVector>) which has a method > > like getZeroVector() (strictly speaking ZeroVector has this method). > > Actual type parameter provides concrete implementation. > > I don't see how this would help. Would I call Zero.getZeroVector()? > Probably you meant something else because this leads to the same > problem with calling static method getZeroVector() on a type > parameter. Could you provide an example? > OK public class MyVector<T, Zero extends ZeroVector> extends Vector2D<T> { .... public MyVector(Zero zero) { this.zero = zero; } .... } MyVector<Integer, Zero2D> vec = new MyVector(Vector2D.zero()); > > > > or suitable simple design pattern (for example > > > > Factory), or even with classic sub-typing (zero vector needs not know > > > > its dimension, it can simply 'answer' with neutral element of the ring > > > > on which it is constructed for each and every component query), > > > > Allowing operations between a concrete vector and this general zero > > > vector would require to also allow operations between 2D and 3D vetors - > > > the original type safety would disappear. > > > I don't get it, could you provide an example? > > If I understood well, you meant something like this: > > Class Vector { > public static Vector getZeroVector(){ > return someSpecialZeroVectorInstance; > } > public abstract Vector add(Vector v); > > } > > Class Vector2D { > public Vector add(Vector v){...} > ... > > } > > class MyClass<V extends Vector> { > ... > V v; // V is some concrete class, such as Vector2D > ... > Vector zero = Vector.getZeroVector(); > v.add(zero); // adding a general Vector zero to concrete v > // if this is allowed, then also the following is > v.add(new Vector3D(1,2,3)); // summing 2D and 3D vector > ... > > > > } Right but implementation of addition surely checks for this case, doesn't it? public void add(Vector<? extends T> v) { if (v.getDimension() != this.getDimension() ) throw new IllegalArgumentException(); } So it suffices to have a factory method for appropriate zero vectors Vector zero = Vector.getZeroVector(2); > > > > no big > > > > win here either (eliminating type erasure is extremely welcome but for > > > > other reasons). One big advantage of inheritance is, in my opinion, that > > > > it enables you to compose more specialized classes from generic ones, it > > > > is easy to imagine algebraic ordering relation between types based on > > > > inheritance. Your version of statics breaks this assumption without > > > > promise of any reward in exchange. > > > > I don't see how it breaks this relation between classes. Also now it is > > > possible to hide supertype's static methods by own implementation. I > > > would only add that in some cases this hiding would be required. > > > I was not very clear, it was late when I was writing :-) I guess what > > I was trying to say was that you can impose ordering based on > > specialization (as opposed to parent-child relationship). Each class > > in an inheritance chain either extends or redefines partially its > > ancestor (I am using 'or' as logical or). Therefore each class is > > either more specialized (if redefinition occurs and it accepts > > stronger contract, as in Rectangle->Square) or equally specialized (if > > extension occurs and all redefinitions do not change contract - I > > treat extension as an interface extension so that class can be used > > _additionally_ in different context). Your proposal forces implementor > > to provide implementation for non-inheritable method, so it really > > can't take any benefit from redefinitions up the chain. Therefore all > > concrete classes are at most equally specialized as their context of > > usage is determined by a static method. So it does not play well with > > most "inheritance patterns". That's how I see it. > > Now I don't get it. Can you provide an example where you have a class > and its specialized subclass and adding an abstract static method to > their interface removes/prohibits this specialization? Yes, consider public abstract class IOStream //for reading disk streams { public abstract static boolean isReadable(File f) //returns true for files which a concrete class can hopefully process. .... } public class LocalIOStream extends IOstream { public static boolean isreadable(File f) { return f.isLocalFile(); } .... } public class AudioVideoStream extends LocalIOStream { ??? } in AVStream you have, if I understood you correctly, two choices - either to redo all work of super-classes which is not really an option, let's say, public static boolean isReadable(File f) { return f.isLocalFile() && (f instanceof AudioFile && ((AudioFile)f).getAudioCodecID().equals (...);} or omit it so then you impose different context. Namely, pretend to be able to read remote files while you are not. And one more question: //client code Stream s = new AudioVideStream(..); read10Bytes(s); public byte[] read10Bytes(Stream s) { if (!Stream.isReadable(file)) //how would you dispatch it? There is no way I suppose }
From: Andreas Leitgeb on 19 Oct 2009 10:13 Tomas Mikula <tomas.mikula(a)gmail.com> wrote: > On Mon, 19 Oct 2009 07:29:24 +0000, Andreas Leitgeb wrote: >> Tomas Mikula <tomas.mikula(a)gmail.com> wrote: >>> presence of no-arg constructor in a serializable class would be checked >>> at compile-time rather than at run-time. >> I think this is easily misunderstood. The newly possible compiletime >> check would be for compiling the *concrete class* whose name you later >> intend to specify dynamically at runtime. This does have some merit. >> >> Still no compiletime check would of course be possible at the place >> where you'd *use* that class dynamically, so nothing at all can be >> helped about the reflection-part of this story. > > The idea here was to automate the reflection. Sorry, that is a non-starter. If you know the class at compiletime, you can just use it with the "new"-operator and have all kinds of compile time checks. If you don't know the class at compiletime, then neither does the compiler, so there's nothing the compiler could possibly do for you beyond what it already does, namely write bytecode to have the JVM check it all at runtime. Even at runtime, there's no saving: both, interface and existence of relevant methods and constructors, each have to be checked separately by the JVM. I still see some merit in being able to enforce that any concrete class implementing some thusly declared interface had to offer some particular c'tor, as a means to help developers of such classes to not forget about it. About the static methods: if you need that kind of enforcement for dynamically used classes, then just use instances and non-static methods as helpers: public interface Foo { // known to the user at compiletime. public void pseudoStatic(); } public class FooBar { // known to the user only at runtime public void pseudoStatic() { realStatic(); } public static void realStatic() { /* do something ... */ } } // snippet of user's code: Foo x = (Foo)use_reflection_to_get_instance(implName); // implName=="FooBar" x.pseudoStatic(); Up to minor syntactical differences this FooBar object does what your ".asImplementationOf()" result was intended to do, if I understood it correctly. I don't think, that calling static methods on dynamically named classes is worth such deep changes as you seem to have in mind for this task.
From: Marcin Rzeźnicki on 19 Oct 2009 10:20
On 19 Paź, 16:13, Andreas Leitgeb <a...(a)gamma.logic.tuwien.ac.at> wrote: > > I still see some merit in being able to enforce that any concrete > class implementing some thusly declared interface had to offer some > particular c'tor, as a means to help developers of such classes to > not forget about it. Yep, this is not bad. |