Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > abstract static methods (again)

Reply
Thread Tools

abstract static methods (again)

 
 
Tom Anderson
Guest
Posts: n/a
 
      10-19-2009
On Mon, 19 Oct 2009, Eric Sosman wrote:

> Andreas Leitgeb wrote:
>
>> On second thought: If the Entertainers were designed to be dynamically
>> loaded by name, then Comedians just wouldn't have any chance of a
>> individual default joke. They could offer their Joke- constructor, but
>> unless they also offered a no-args one, they just wouldn't ever be
>> successfully engaged.

>
> But I admit that my familiarity with frameworks of this kind is
> slight. Perhaps they're just not suited for classes whose instances
> lack obvious defaults. (Maybe they're only good for singletons?)


They have a mechanism for configuring objects as well as creating them. I
use one which for each object you want to create, there's a property file,
which looks like:

$class=com.sosman.strawman.Comedian
joke=A compiler, a linker, and an editor walk into a bar ...

Which is translated by the reflective machinery into calls like:

Class cl = Class.forName("com.sosman.strawman.Comedian");
Object obj = cl.newInstance();
cl.getMethod("setJoke", String.class).invoke(obj, "A compiler, a linker, and an editor walk into a bar ...");

With some more stuff to deal with properties that aren't strings. It's not
pretty, but it quite often works.

It might be better if the framework tried to find a constructor which
would take the specified parameters, but it's not obvious how you'd do
that. However, i don't see how Tomas's proposal would help.

tom

--
Civis Britannicus sum.
 
Reply With Quote
 
 
 
 
Tom Anderson
Guest
Posts: n/a
 
      10-19-2009
On Mon, 19 Oct 2009, Tomas Mikula wrote:

> Now I present two examples where it would be useful.
>
> (1) Eliminate or reduce the use of reflection in serialization frameworks.


This example isn't actually about your proposal, it's about ...

> a new magic class Implementation<T>


.... so i'm going to ignore it.

> (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. [...] 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.


This is a good use case. But i suspect it can be done with java as it
stands now - rather than reified generics, you factor out a Type Object,
as the patternists call it. Vectors can tell you their type object, and
the type object can give you a zero.

Like this, for instance:

http://urchin.earth.li/~twic/Code/Mu...cs/Vector.java

Now, i should say that that is some fairly bonkers generics (in fact, i
think i can now claim Double Wizard status at generics). It took me a good
while to get the types straight, and even now, the declarations are of a
mind-searing eldritch uncanniness verging on the Lovecraftian.

But what we need to fix this is some more concise generics syntax, not
some semantically befuddled new kind of method inheritance. I can't say
exactly what, though.

tom

--
Civis Britannicus sum.
 
Reply With Quote
 
 
 
 
Tom Anderson
Guest
Posts: n/a
 
      10-19-2009
On Mon, 19 Oct 2009, Andreas Leitgeb wrote:

> Eric Sosman <> wrote:
>> Andreas Leitgeb 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.

>
>> Here's my objection: Suppose there's an Entertainer interface
>> (or abstract class) and ...
>> ...
>> Okay, it might make sense for the class of Comedians to have a
>> default stale Joke (a faithful model of reality, perhaps), ...

>
>> ...
>> The author of Entertainer, who knew nothing about the wants and needs
>> of those who would come later, ...

>
> Thanks for the entertaining example, but I think it's beside the point.
> This type of argument "it's bad for this exemplary usecase, so it must
> be bad for all usecases" is obviously flawed. (or was a joke, itself)
>
> On second thought: If the Entertainers were designed to be dynamically
> loaded by name, then Comedians just wouldn't have any chance of a individual
> default joke. They could offer their Joke- constructor, but unless they
> also offered a no-args one, they just wouldn't ever be successfully engaged.
>
> This whole topic is inspired by dynamic loading of classes. Otherwise, there
> wouldn't really be any use for dictating constructors at all. Dynamic loading
> of classes seems to me of increasing importance with all those AppServers,
> J2EE, ... Demanding the default-constructor (or even with a specific set
> of arguments) for those classes imposes no new restriction, just formalizes
> the restrictions that were already imposed by documentation and use.


This problem was solved in the golden age of the Patternists. The solution
is that you don't load Entertainers, you load EntertainerAgencies.

public interface EntertainerAgency {
public Entertainer hire();
}

String agencyName = loadFromWherever();
EntertainerAgency agency = (EntertainerAgency)Class.forName(agencyName).newIn stance();
Entertainer e = agency.hire();

The question of some putative Entertainer constructor goes away. You do
have the question of the EntertainerAgency constructor, but this is much
less pressing. If it really worries you, use a EntertainerAgencyFactory.

Before you ask, yes, it's factories all the way down. Until you reach the
turtles.

tom

--
Ideas are bulletproof. -- V
 
Reply With Quote
 
Tom Anderson
Guest
Posts: n/a
 
      10-19-2009
On Mon, 19 Oct 2009, Andreas Leitgeb wrote:

> Marcin Rze?nicki <> wrote:
>> On 19 Pa?, 17:32, Arved Sandstrom <dces...@hotmail.com> wrote:
>>> Marcin Rze?nicki wrote:
>>>> On 19 Pa?, 16:13, Andreas Leitgeb <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.
>>> I prefer the annotations-based method such as described here:
>>> http://www.javaspecialists.eu/archive/Issue167.html

>> Nice, it wins

>
> Indeed nice, but what would be the extra effort to create e.g. a
> @StringArgConstructor annotation and its processing? And then also
> a @StringStringArgConstructor and a @StringMyFooIntArgConstructor, ...


Or maybe just a @DefinedConstructor annotation that takes an array of
classes as a parameter.

tom

--
Ideas are bulletproof. -- V
 
Reply With Quote
 
Tomas Mikula
Guest
Posts: n/a
 
      10-19-2009
On Mon, 19 Oct 2009 20:19:51 +0100, Tom Anderson wrote:

> On Mon, 19 Oct 2009, Eric Sosman wrote:
>
>> Andreas Leitgeb wrote:
>>
>>> On second thought: If the Entertainers were designed to be dynamically
>>> loaded by name, then Comedians just wouldn't have any chance of a
>>> individual default joke. They could offer their Joke- constructor,
>>> but unless they also offered a no-args one, they just wouldn't ever be
>>> successfully engaged.

>>
>> But I admit that my familiarity with frameworks of this kind is
>> slight. Perhaps they're just not suited for classes whose instances
>> lack obvious defaults. (Maybe they're only good for singletons?)

>
> They have a mechanism for configuring objects as well as creating them.
> I use one which for each object you want to create, there's a property
> file, which looks like:
>
> $class=com.sosman.strawman.Comedian
> joke=A compiler, a linker, and an editor walk into a bar ...
>
> Which is translated by the reflective machinery into calls like:
>
> Class cl = Class.forName("com.sosman.strawman.Comedian"); Object obj =
> cl.newInstance();
> cl.getMethod("setJoke", String.class).invoke(obj, "A compiler, a
> linker, and an editor walk into a bar ...");
>
> With some more stuff to deal with properties that aren't strings. It's
> not pretty, but it quite often works.
>
> It might be better if the framework tried to find a constructor which
> would take the specified parameters, but it's not obvious how you'd do
> that. However, i don't see how Tomas's proposal would help.


The use of my proposal here would be to enforce a constructor or a static
creator method that would create an initialized object from
ObjectInputStream/JAXBElement/javolution.xml.XMLFormat.InputElement
/...
 
Reply With Quote
 
Arved Sandstrom
Guest
Posts: n/a
 
      10-19-2009
Tom Anderson wrote:
> On Mon, 19 Oct 2009, Andreas Leitgeb wrote:
>
>> Marcin Rze?nicki <> wrote:
>>> On 19 Pa?, 17:32, Arved Sandstrom <dces...@hotmail.com> wrote:
>>>> Marcin Rze?nicki wrote:
>>>>> On 19 Pa?, 16:13, Andreas Leitgeb <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.
>>>> I prefer the annotations-based method such as described here:
>>>> http://www.javaspecialists.eu/archive/Issue167.html
>>> Nice, it wins

>>
>> Indeed nice, but what would be the extra effort to create e.g. a
>> @StringArgConstructor annotation and its processing? And then also
>> a @StringStringArgConstructor and a @StringMyFooIntArgConstructor, ...

>
> Or maybe just a @DefinedConstructor annotation that takes an array of
> classes as a parameter.
>
> tom
>

That's the way I would do it - I managed to get an example of such
working after some anguish (I am not _that_ familiar with the annotation
processing APIs). To use the example provided in my cite, you can pick
off the AnnotationMirror for the Element annotated with
@DefinedConstructor, and use that (to wit, getElementValues()) to
retrieve the classes that you've put into a parameter of the
annotation...this just gets passed down the chain to the visitor. And
down in the visitor, the actual parameters to the ctor are available
via getParameterTypes() on the ExecutableElement.

I find the APIs a bit painful, and maybe others do as well. But on the
plus side, you only need to define a utility annotations processor once,
and then supply it (and others) in a JAR for javac to use. Something
like a @DefinedConstructor annotation _is_ going to cover a lot of
cases, so it's worth the effort, IMHO.

AHS
 
Reply With Quote
 
Tomas Mikula
Guest
Posts: n/a
 
      10-19-2009
On Mon, 19 Oct 2009 11:37:07 -0700, Marcin Rzeźnicki wrote:

> On 19 Paź, 19:53, Tomas Mikula <tomas.mik...@gmail.com> wrote:
>> > Right but implementation of addition surely checks for this case,
>> > doesn't it?

>>
>> Not necessarily:
>>
>> abstract class Vector<V extends Vector<V>> {
>> public V add(V v);
>>
>> }
>>
>> class Vector2D extends Vector<Vector2D> {
>> private final int x, y;
>> public Vector2D(int x, int y){ this.x = x; this.y = y; } public
>> Vector2D add(Vector2D v){
>> return new Vector2D(this.x + v.x, this.y + v.y);
>> }
>>
>> }
>>
>> No checking that the argument of addition has the correct type, because
>> this is enforced by the compiler.
>>
>>
>>

> Formal arguments have to be invariant with respect to overriding in
> Java, you simply created method overload which will be used when
> compiler is sure that runtime type of argument will be Vector2D. You
> will still have to provide 'generic' add method.


No. Notice how add() is declared in Vector:
public V add(V v);
It works on type V.
When Vector2D is declared as
Vector2D extends Vector<Vector2D>,
Vector2D is substituted for V. So Vector2D's add() method is only
required to work on Vector2D instances. If Vector2D was declared as
Vector2D<V extends Vector<V>> extends Vector<V>,
then Vector2D would have to implement the add() method that takes any
subclass of Vector and returns the same subclass of Vector as it takes.

> Your example does not
> help either (or I cannot see how it would) because you will not be able
> to dispatch on v's actual type unless you change how invokestatic works.


I'm not sure if I understand, but in the implementation of Vector2D V is
bound to Vector2D at compile time.

>> > 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
>> > (...);}

>>
>> You don't have to redo the work, you can call the superclass's static
>> method as usual:
>>
>> public static boolean isReadable(File f){
>> return LocalIOStream.isReadable(f) &&
>> f instanceof AudioFile &&
>> ((AudioFile)f).getAudioCodecID().equals(...);
>>
>> }

>
> Yeah, right, but consider what happens when someone implements multiple
> interfaces, or when inheritance tree changes, or when someone inherits
> multiple interfaces with conflicting statics and so on.


Right now I can't think of any problems different from those with non-
static methods.

> This example is
> basically hand-crafted implementation of virtual dispatch
>
> ...
>
> Well, ok, but it does not change anything. Still you have to re-
> implement invokevirtual by hand all the time


Well, if you want to extend the behavior of a non-static method, you
still have to call the inherited method by hand (super.someMethod()) and
then do your specific work. This is no different from my example. The
only real disadvantage is when you want to inherit the method as is. Yes,
this is not possible with my proposal and you have to call the
superclass's method by hand. Though my proposal was targeted at uses
where you want to provide own implementation in each class. But I'm
finally getting what you are trying to say - that this feature might
encourage design that will later turn out as wrong. Yes, there might be
this danger, as is with many other features.

>> > 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

>>
>> > }

>>
>> This would be a compile-time error, since isReadable() is abstract in
>> Stream.

>
> This is really bad Then actually your statics will be usable only
> when you know exact type you want to work with.


And with generics and with dynamic loading.
 
Reply With Quote
 
Arved Sandstrom
Guest
Posts: n/a
 
      10-19-2009
Tom Anderson wrote:
[ SNIP ]

> Now, i should say that that is some fairly bonkers generics (in fact, i
> think i can now claim Double Wizard status at generics). It took me a
> good while to get the types straight, and even now, the declarations are
> of a mind-searing eldritch uncanniness verging on the Lovecraftian.

[ SNIP ]

I'll have to use that theme at a code review:

"This tenebrous source, wrought of a minion of Azathoth, must be
consigned to the subterranean depths ere this codebase suffers the fate
of all software that embraces the ultimate mindless chaos."

AHS
 
Reply With Quote
 
Tomas Mikula
Guest
Posts: n/a
 
      10-19-2009
On Mon, 19 Oct 2009 21:05:05 +0100, Tom Anderson wrote:

> On Mon, 19 Oct 2009, Tomas Mikula wrote:
>
>> Now I present two examples where it would be useful.
>>
>> (1) Eliminate or reduce the use of reflection in serialization
>> frameworks.

>
> This example isn't actually about your proposal, it's about ...
>
>> a new magic class Implementation<T>

>
> ... so i'm going to ignore it.
>
>> (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. [...] 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.

>
> This is a good use case. But i suspect it can be done with java as it
> stands now - rather than reified generics, you factor out a Type Object,
> as the patternists call it. Vectors can tell you their type object, and
> the type object can give you a zero.
>
> Like this, for instance:
>
> http://urchin.earth.li/~twic/Code/Mu...cs/Vector.java


The VectorKind should also have two type parameters to get rid of
compiler warnings and to map Vectors to VectorKinds one-to-one:

abstract class
VectorKind<V extends Vector<V,K>, K extends VectorKind<V,K>>

Anyway, this is not of any help for me, because you are obtaining the
VectorKind instance from an instance of Vector. If there is always an
instance of Vector at hand, I can obtain the zero directly from that
instance (just move the abstract zero() method you declared in VectorKind
to Vector). The problem is that there is not always an instance at hand
and it is cumbersome to artificially pass one. The result is that the
readability of code suffers a lot, because it contains the workarounds,
not the actual work.
 
Reply With Quote
 
Tom Anderson
Guest
Posts: n/a
 
      10-19-2009
On Mon, 19 Oct 2009, Tomas Mikula wrote:

> On Mon, 19 Oct 2009 21:05:05 +0100, Tom Anderson wrote:
>
>> http://urchin.earth.li/~twic/Code/Mu...cs/Vector.java

>
> The VectorKind should also have two type parameters to get rid of
> compiler warnings and to map Vectors to VectorKinds one-to-one:
>
> abstract class
> VectorKind<V extends Vector<V,K>, K extends VectorKind<V,K>>


It compiled without warnings for me - but then i'm on 1.5.

> Anyway, this is not of any help for me, because you are obtaining the
> VectorKind instance from an instance of Vector. If there is always an
> instance of Vector at hand, I can obtain the zero directly from that
> instance (just move the abstract zero() method you declared in
> VectorKind to Vector). The problem is that there is not always an
> instance at hand and it is cumbersome to artificially pass one.


What are you planning to do with this zero if you don't have any Vector
instances? I don't really buy your scenario.

tom

--
NO REAL THAN YOU ARE -- Ego Leonard, The Zandvoort Man
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Abstract Static methods ankur Java 5 11-26-2007 07:19 AM
Re: Abstract Methods & Abstract Class Gerald Klix Python 1 10-20-2005 02:44 PM
Abstract Methods & Abstract Class Iyer, Prasad C Python 0 10-20-2005 06:35 AM
Abstract Classes w/o abstract methods DaKoadMunky Java 4 04-20-2004 04:53 AM
Abstract Static Methods Icosahedron C++ 1 01-30-2004 02:34 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57