![]() |
abstract static methods (again)
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. By "abstract static method" I refer to either a static method in an interface or an abstract static method of an abstract class. Put shortly, a declaration of an abstract static method in interface J (resp. in abstract class A) would mean that any class implementing J (resp. extending A) must either provide its _own_ implementation of that static method, or itself be abstract. Note 1: There would still be no inheritance of static methods. Note 2: Semantics of calling static methods on instances would remain unchanged, i.e. static methods are still not virtual. Note 3: The following would be a compile-time error: interface J { public static void f(); } class X implements J { public static void f(){...} } class Y extends X { } // ERROR: class Y does not provide // its _own_ implementation of f() Note 4: Abstract constructors could be allowed, too. interface Serializable { public abstract Serializable(); } This would require each implementation of Serializable to provide a public no-arg constructor. (Maybe the following would be a better syntax: interface Serializable<S extends Serializable> { public abstract S(); } ) Now I present two examples where it would be useful. (1) Eliminate or reduce the use of reflection in serialization frameworks. One example was given in Note 4 --- the presence of no-arg constructor in a serializable class would be checked at compile-time rather than at run- time. For a more sophisticated usage some new API and additional support from compiler is required. (The following may not be the best way to extend the API, but I hope it will serve well for illustration.) Imagine a new magic class Implementation<T>. This class will have no methods on its own, but on its instances we will be able to call the same methods as on the class T. (For this, the compiler magic would be necessary.) Example: interface J { J(int x); static void f(); void g(); } class A implements J { A(int x){...} static void f(){...} void g(){...} } Implementation<J> I = A.class.asImplementationOf(J.class); I.new(5); // OK, calling the constructor A(int x) I.f(); // OK, calling static method A.f() I.g(); // ERROR, calling an instance method without an instance of J Notice extending the Class API by adding new method <T> Implementation<T> asImplementationOf(Class<T> clazz); The restriction would apply that the type T is known at compile time. Now back to usage in serialization frameworks. The above API would automate the verification that all required constructors and static methods are present in a class: interface MySerializable<S extends MySerializable<S>> { public static S readObject(ObjectInputStream in); } Class<?> cls = Class.forName("com.example.MySerializableClass"); Implementation<MySerializable> M = cls.asImplementationOf(MySerializable.class); MySerializable obj = M.readObject(in); Note that the verification that MySerializableClass really implements MySerializable interface would be automatically done in the Class.asImplementationOf() method, thus saving much of the reflection code. (2) The second use case is with generics, but would require reified generics (which I hope will appear in some future version of Java). Suppose you have an abstract class Vector which represents a vector in a vector space (don't confuse with java.util.Vector) and a few implementations, like Vector2D and Vector3D. abstract class Vector<V extends Vector<V>> { public abstract V add(V v); // returns the sum of v and this ... } class Vector2D extends Vector<Vector2D> { public static Vector2D zero(); // returns (0,0) ... } class Vector3D extends Vector<Vector3D> { public static Vector3D zero(); // returns (0,0,0) ... } Now let's have a generic class that will use vectors and do operations on them, but doesn't really care about their actual dimension. So it will work with abstract type Vector. But for some operations it may be necessary to obtain the zero vector, without explicitely knowing the actual type of vector. We may want to write something like this: class MyClass<V extends Vector<V>> { public void someMethod(){ V v = V.zero(); ... } } This is of course not possible, but could be made possible if Vector specified abstract static method zero(): abstract class Vector<V extends Vector<V>> { public static abstract V zero(); public abstract V add(V v); ... } We would further change the declaration of MyClass to class MyClass<V implements Vector<V>> { ... } The keywork extends was exchanged for implements (another syntax extension). The compiler would know that a type parameter V that fully implements all abstract static methods of Vector is required (so, for example, Vector itself would not be a valid type parameter of MyClass). |
Re: abstract static methods (again)
On Sun, 18 Oct 2009 19:19:55 -0700, Peter Duniho wrote:
> Tomas Mikula 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 :). [...] > > You aren't the first. However, in C++, C#, Java, and languages like > them, you simply are never going to have methods that are both virtual > and static. And since abstract implies virtual, that rules out abstract > static methods too. I'm not talking about virtual static methods. In this case, abstract would not imply virtual. My second use case could most probably be accomplished in C++ by Concepts (though Concepts didn't make it to C+ +0x). In fact, it is achievable with current C++ templates, only without compile time checking --- it is possible to call T::staticMethod() where T is a template parameter. |
Re: abstract static methods (again)
On 19 Paź, 04:06, Tomas Mikula <tomas.mik...@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. Example with generics can easily be substituted by some kind of "trait" parameter 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), 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. However, I like the idea of "interface constructor". It might be handy to force every client to provide necessary piece of data. To be more useful for this purpose I'd postulate to create the rule which says that every derived constructor has to call this 'interface constructor'. But still, no big deal. It is possible to impose semantics I am talking about with or without it. |
Re: abstract static methods (again)
On 10/18/2009 10:06 PM, Tomas Mikula 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. I saw a more detailed proposal at <http://kijaro.dev.java.net>, which included a prototype implementation. The specification for said stuff is linked here: <http://www.jroller.com/jadda/entry/meta_interfaces_revisited>. -- Beware of bugs in the above code; I have only proved it correct, not tried it. -- Donald E. Knuth |
Re: abstract static methods (again)
Tomas Mikula <tomas.mikula@gmail.com> wrote:
> I have searched this group for "abstract static methods" ... > ... 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. There's still a slight "problem" with abstract static methods: With respect to static members, *every* class is concrete. Maybe you thought about static "create"-methods, as alternative to enforced constructors? |
Re: abstract static methods (again)
On Mon, 19 Oct 2009 07:29:24 +0000, Andreas Leitgeb wrote:
> Tomas Mikula <tomas.mikula@gmail.com> wrote: >> I have searched this group for "abstract static methods" ... ... >> 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. Suppose a class is required to have many static methods. Instead of checking if they are actually present and have the correct signature manually, the method Class.asImplementationOf(MyInterface.class) would do all the checking for me. > There's still a slight "problem" with abstract static methods: With > respect to static members, *every* class is concrete. Maybe you thought > about static "create"-methods, as alternative to enforced constructors? If an abstract class MyClass does not have an implementation of a static abstract method staticMethod() specified in its superclass/interface, it can be detected in both the direct use and through reflection: MyClass.staticMethod(); // this would be a compile-time error Class.forName("MyClass").asImplementationOf(MyInte rface.class); // this would be a run-time error My view is that with respect to abstract static members, not every class would be concrete. |
Re: abstract static methods (again)
On Sun, 18 Oct 2009 19:58:43 -0700, Marcin Rzeźnicki wrote:
> On 19 Paź, 04:06, Tomas Mikula <tomas.mik...@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). > 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()? > 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. > 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. |
Re: abstract static methods (again)
On 19 Paź, 13:08, Tomas Mikula <tomas.mik...@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...@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? > > 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. > > 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? > > Â*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. |
Re: abstract static methods (again)
On 19 Pa¼, 14:19, Marcin Rze¼nicki <marcin.rzezni...@gmail.com> wrote:
> On 19 Pa¼, 13:08, Tomas Mikula <tomas.mik...@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 :-) |
Re: abstract static methods (again)
On Oct 19, 2:19*pm, Marcin Rze¼nicki <marcin.rzezni...@gmail.com>
wrote: > On 19 Pa¼, 13:08, Tomas Mikula <tomas.mik...@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...@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? |
| All times are GMT. The time now is 07:53 AM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.