can this be done with generics?

A

Arne Vajhøj

Yes, that's right. Or you need a semi-typed language like Objective-C
where you can do things exactly as intended in your port. Objective-C
has a special type named "id", which will be of the type at runtime
of the object returned at runtime. The Objective-C will issue a
warning when you return an object of type id and leave things to your
responsability whether things will work well.

Sounds similar to C# dynamic.

But it is still a dynamic typed language feature in an otherwise
static typed language.

Arne
 
A

Arne Vajhøj

The OP says nothing about doing the call on a reference of type Foo. In
fact, he explicitly talks about the compiler having all the information
needed.

Having a language feature that works in some cases but not in
other cases depending on whether the compiler can see the
constructor or not is not a good design.

Arne
 
A

Arne Vajhøj

I don't think the compiler has all the information needed to guarantee
that new Bar().foo1().bar() will be executable at runtime. The compiler
may know, from the "return this" in foo1 that it's safe if you run with
the Foo.class and the Bar.class files that it is now generating. But the
compiler also should know that the Bar.class file it's writing may be
run with a Foo.class file from a later compile of a Foo.java that's been
changed

Incompatible changes to a dependency class later does not bother
many other language constructs.

Arne
 
S

Silvio

Having a language feature that works in some cases but not in
other cases depending on whether the compiler can see the
constructor or not is not a good design.

Arne

Nonsense. The compiler does not need to see the constructor or the
method definition. The method could just as well be in an interface (a
trait in Scala terminology).
The type "this.type" is a singleton type that is unique for each object.
It is simply an explicit construct that says the return value of a
method in a class or interface X is the object itself. Among other
things that means that if it is called on a reference of type Y (where Y
is a subtype of X) the return type is Y and not X.

The construct can be used to achieve what the OP intended. It has a more
important function in Scala though. Scala has path dependent types where
not only the type but also the actual identity returned by a method can
be significant. With path dependent types you sometimes need to narrow
the return type of a method in class X to this.type instead of X to
express that no other instance of X will be returned.

Nothing weird going on here and not very much different from covariant
return in Java where the type of the reference matters as well.

Silvio

For those interested, a tiny example:

class X
{
class Y

def me : X = this
def myself : this.type = this

def createY = new Y

var y : Y = _
}

val x1 = new X
val x2 = new X

x1.y = x1.myself.createY //fine
x2.y = x2.me.createY //type mismatch, expected x2.Y found X#Y
x1.y = x2.y //type mismatch, expected x1.Y found x2.Y
x2.y = x1.createY //type mismatch, expected x2.Y found x1.Y

Here x1.Y is type Y from X instance x1 while X#Y is the less restricted
type of all Ys from any X.
 
A

Andreas Leitgeb

Arne Vajhøj said:
Having a language feature that works in some cases but not in
other cases depending on whether the compiler can see the
constructor or not is not a good design.

Your claim itself is trivially correct, but it has nothing to do
with this thread's topic. :) (The premises are not held - the
compiler would have a reliable source for the relevant information.)
 
M

Mike Amling

Incompatible changes to a dependency class later does not bother
many other language constructs.

Yes, in particular I've noticed the hijinks that the switch (enum
instance) bytecode goes through to get runtime compatibility with a
separately modified and recompiled enum class.

Mike Amling
 
A

Andreas Leitgeb

Robert Klemme said:
public class Foo<T extends Foo<?>> {
public T foo() { /* do stuff */ return self(); }

@SuppressWarnings("unchecked")
protected final T self() { return (T) this; }

public static void main(String[] args) {
new Baz<Baz<?>>().foo().baz().bar();
new TheEnd().foo().last().baz().bar();
}
}

class Bar<T extends Bar<?>> extends Foo<T> {
public T bar() { /* do stuff */ return self(); }
}
class Baz<T extends Baz<?>> extends Bar<T> {
public T baz() { /* do stuff */ return self(); }
}

Finally I got my head around it.

This is f***ing brilliant && you're genious!

For the extra win, my "source" of objects are really static factory methods,
instead of "new"s, so the code on users' end now essentially looks like this:

getFoo().foo() /* compiler would correctly refuse .bar() or .baz() here */ ;
getBar().foo().bar() /* compiler would correctly refuse .bar() here */ ;
getBaz().foo().bar().baz(); /* all fine */

It can't get any better than that.

(In case it's already too long since I last said it: you're genious!)

Thanks also to Patrick for his draft!
 
A

Andreas Leitgeb

Arivald said:
W dniu 2013-11-26 01:50, Andreas Leitgeb pisze:
Maybe this way it looks better to use:
new Bar().foo().cast(Bar.class).bar();

Yeah, slightly better, but nothing (within the limitations of current Java)
can beat Robert's solution.

Thanks, anyway :)
 
S

Sebastian

Am 27.11.2013 19:53, schrieb Andreas Leitgeb:
Robert Klemme said:
public class Foo<T extends Foo<?>> {
public T foo() { /* do stuff */ return self(); }

@SuppressWarnings("unchecked")
protected final T self() { return (T) this; }

public static void main(String[] args) {
new Baz<Baz<?>>().foo().baz().bar();
new TheEnd().foo().last().baz().bar();
}
}

class Bar<T extends Bar<?>> extends Foo<T> {
public T bar() { /* do stuff */ return self(); }
}
class Baz<T extends Baz<?>> extends Bar<T> {
public T baz() { /* do stuff */ return self(); }
}

Finally I got my head around it.

This is f***ing brilliant && you're genious!

For the extra win, my "source" of objects are really static factory methods,
instead of "new"s, so the code on users' end now essentially looks like this:

getFoo().foo() /* compiler would correctly refuse .bar() or .baz() here */ ;
getBar().foo().bar() /* compiler would correctly refuse .bar() here */ ;
getBaz().foo().bar().baz(); /* all fine */

It can't get any better than that.

(In case it's already too long since I last said it: you're genious!)

Thanks also to Patrick for his draft!

I'm late butting in this discussion, but this looks related to the
"getThis() trick", see here:
http://www.angelikalanger.com/GenericsFAQ/FAQSections/ProgrammingIdioms.html#FAQ206

That explanation might help in understanding Robert's coding.

-- Sebastian
 
A

Andreas Leitgeb

Sebastian said:
Am 27.11.2013 19:53, schrieb Andreas Leitgeb:
Robert Klemme said:
public class Foo<T extends Foo<?>> {
public T foo() { /* do stuff */ return self(); }

@SuppressWarnings("unchecked")
protected final T self() { return (T) this; }

public static void main(String[] args) {
new Baz<Baz<?>>().foo().baz().bar();
new TheEnd().foo().last().baz().bar();
}
}

class Bar<T extends Bar<?>> extends Foo<T> {
public T bar() { /* do stuff */ return self(); }
}
class Baz<T extends Baz<?>> extends Bar<T> {
public T baz() { /* do stuff */ return self(); }
}

I'm late butting in this discussion, but this looks related to the
"getThis() trick", see here:
http://www.angelikalanger.com/GenericsFAQ/FAQSections/ProgrammingIdioms.html#FAQ206

Thanks for the pointer.

Related, yes. Essentially it is what Patrick first suggested.

While Angelika Langer covers the base for nice class hierarchies, where
only leaf-classes are not abstract (and therefore can do without casts),
Robert traded castfree-ness for the ability to do it with hierarchies
involving instanciable non-leaf classes.

The risks of accepting the cast can be summarized in a short example:
new Foo<Bar<?>>().bar(); // compiles fine, throws later.
and I'm fine with taking that risk in my context.
 
D

Daniel Pitts

I'd like to use the "call methods in a chain" pattern
across a class-subhierarchy, with most of the methods
defined in the base-class.

Suppose, I had two classes:

class Foo {
public Foo foo1() {
/* do something very interesting ... */
return this;
}
// assume there were like 100 such foo#() methods here
// (in practice they of course have more diverse names)
}
class Bar extends Foo {
public Bar bar() {
/* do something very interesting */
return this;
}
}

And then, somewhere else:

// the single-class chain works just fine:
new Foo().foo1().foo42().foo84();

// but if I start with a Bar, and eventually after some foo#() calls
// want to call method bar() which is not in Foo, then I'm out of luck:
new Bar().foo1().foo42().foo84().bar(); // doesn't work, of course!

Is there a way to use *generics* for the methods of class Foo such that
each foo#() returns the *static* type on which the compiler saw it
applied?

Alternatives, that do NOT satisfy me:
a) use an explicit cast to (Bar)
((Bar)(new Bar().foo1().foo42().foo84())).bar();
Would turn into a nightmare, when more of Bar's
methods got mixed into the chain.
b) override each of the 100 foo#()s in Bar with a Bar return-type.
Would turn into a nightmare, when more sub-classes like Bar
appeared, or new methods added to Foo.
(Note, that "bad performance" due to extra calls is NOT my concern here)
c) add "Foo bar() { return this; }" in Foo.
Would turn into a nightmare, when more sub-classes like Bar
appeared (and Foo would have to reflect all subclasses' methods),
or some chain accidentally called a subclass method on a chain
started from some other class's instance, and compiler wouldn't
detect the mistake.

I'm pretty sure, that this would be principially possible (as in: the
compiler has all the information that would be needed), but I can't seem
to find an approach for how to capture the static type of the expression
on which the (non-static) method is called.

Thanks in advance!

Yes, this *can* be done with generics, but its relatively ugly and hard
to maintain. I've been doing a lot of work in PHP lately, and they have
a return type hint "@return $this", which makes my IDE of choice
recognize the intent. Java, though superior in many ways, is lacking
that kind of ability.


To answer your question though:

abstract class Foo<T extends Foo<T>> {

public T foo1() { return getThis(); }

protected abstract T getThis();

}

class Bar extends Foo<Bar> {

public Bar bar1() { /* something interesting */ return this; }
protected T getThis() { return this; }
}



It gets uglier if you need multiple levels of inheritance, or if you
have two classes which refer to each other.
 
A

Andreas Leitgeb

Daniel Pitts said:
Yes, this *can* be done with generics, but its relatively ugly and hard
to maintain.

Thanks for the answer, but you're a bit late to the party, and both the
getThis()-approach as well as a slightly "dirtier"(with unchecked casts)
solution that also works with instanciable non-leaf-classes have already
been posted. :)
 
D

Daniel Pitts

Thanks for the answer, but you're a bit late to the party, and both the
getThis()-approach as well as a slightly "dirtier"(with unchecked casts)
solution that also works with instanciable non-leaf-classes have already
been posted. :)
Yeah, I saw that after I posted :)

Cheers.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,090
Messages
2,570,603
Members
47,223
Latest member
smithjens316

Latest Threads

Top