Java Forum / General / May 2007
Function that returns derived class?
aaronfude@gmail.com - 07 May 2007 23:23 GMT Hi,
I want to define a function in the base class that will do some stuff and then "return this;" but in a such a way that when called on an object of a derived class it will return an instance of that class?
public class A { public A cool() { System.out.println("Hello, World"); return this; } }
public class B extends A { public void anotherFunction() {
} }
And then I want the following to work
new B().cool().anotherFunction();
Thank you,
Aaron Fude
Piotr Kobzda - 07 May 2007 23:40 GMT > I want to define a function in the base class that will do some stuff > and then "return this;" but in a such a way that when called on an [quoted text clipped - 11 lines] > > } public B cool() { super.cool(); return this; }
> } > > And then I want the following to work > > new B().cool().anotherFunction(); piotr
Hendrik Maryns - 08 May 2007 10:21 GMT Piotr Kobzda schreef:
>> I want to define a function in the base class that will do some stuff >> and then "return this;" but in a such a way that when called on an [quoted text clipped - 18 lines] > >> } I guess you meant
public B cool() { return super.cool(); }
That’s the way I’d prefer.
Note that this is only available in Java 1.5+ (covariant return types).
H. - -- Hendrik Maryns http://tcl.sfs.uni-tuebingen.de/~hendrik/ ================== http://aouw.org Ask smart questions, get good answers: http://www.catb.org/~esr/faqs/smart-questions.html
Piotr Kobzda - 08 May 2007 10:54 GMT > Piotr Kobzda schreef:
>> public B cool() { >> super.cool(); >> return this; >> }
> I guess you meant > > public B cool() { > return super.cool(); > } No. It doesn't compile.
> That’s the way I’d prefer. I guess you meant:
public B cool() { return (B) super.cool(); }
My intent was to prevent from unnecessary cast.
piotr
Hendrik Maryns - 08 May 2007 11:36 GMT Piotr Kobzda schreef:
>> Piotr Kobzda schreef: > [quoted text clipped - 10 lines] > > No. It doesn't compile. Really? Sorry for not testing. That should be a bug. Hm, well no, ok. The compiler is not supposed to know ‘this’ is returned, it just knows it is an A. You’re right.
>> That’s the way I’d prefer. > [quoted text clipped - 5 lines] > > My intent was to prevent from unnecessary cast. Makes sense.
H. - -- Hendrik Maryns http://tcl.sfs.uni-tuebingen.de/~hendrik/ ================== http://aouw.org Ask smart questions, get good answers: http://www.catb.org/~esr/faqs/smart-questions.html
Spring Liu - 08 May 2007 00:41 GMT On May 8, 6:23 am, aaronf...@gmail.com wrote:
> Hi, > [quoted text clipped - 24 lines] > > Aaron Fude ((B) new B().cool()).anotherFunction();
aaronfude@gmail.com - 08 May 2007 01:41 GMT Can the overriding and the casts be avoided with some kind of template structure?
Thanks
> On May 8, 6:23 am, aaronf...@gmail.com wrote: > [quoted text clipped - 30 lines] > > - Show quoted text - Ben Schumeth - 08 May 2007 08:57 GMT > Can the overriding and the casts be avoided with some kind of template > structure? I very much doubt it, since there are no templates in Java. Despite the unfortunate similarity in syntax, Java generics are nothing like C++ templates (for details search the newsgroup archives).
class A { public <T extends A> T cool( T in ) // parameter is used to determine return type { System.out.println("Hello, World"); return (T)this; } }
class B extends A { public void anotherFunction() { System.out.println("other func"); } }
B myB = new B(); myB.cool( myB ).anotherFunction();
No casting in the calling code, but is this really any better than what Piotr and Liu suggested? I doubt it.
Ben
 Signature Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
Piotr Kobzda - 08 May 2007 09:52 GMT > Can the overriding and the casts be avoided with some kind of template > structure? As Ben already explained, there are no "template structures" in Java.
Assuming a "kind of ..." means Java generics, just another simple approach in your case might be:
public class A<T extends A> { public T cool() { System.out.println("Hello, World"); return (T)this; // unsafe! } }
public class B extends A<B> { public void anotherFunction() { } }
It allows for usage like that:
new A().cool(); // raw type A is used here! new B().cool().anotherFunction();
However, mixing a raw and parameterized types is discouraged, and usage of it is limited to a single level of inheritance only (erasure of B declared as "class B<T extends B<T>> extends A<T>", without overriding a cool() method, results in A (not B) taken as a return type for that method).
Safer approach is to have a generic base class for A and B:
public abstract class Base<T extends Base<T>> { protected abstract T getT();
public T cool() { System.out.println("Hello, World"); return getT(); } }
public class A extends Base<A> { protected A getT() { return this; } }
public class B extends Base<B> { protected B getT() { return this; }
public void anotherFunction() { } }
There is no problem now in using A and B the way you expect (there is also easy way to extend that "pattern" with other classes, e.g. introducing another generic base class for B derived from the A's base class). Unfortunately, it disallows a direct inheritance of A from B, so then B can not be used as replacement of A anymore. Partial solution for that problem may appear already mentioned extended version of that "pattern", i.e.:
public abstract class ABase<T extends ABase<T>> { protected abstract T getT();
public T cool() { System.out.println("Hello, World"); return getT(); } } public abstract class BBase<T extends BBase<T>> extends ABase<T> { public void anotherFunction() { } }
public class A extends ABase<A> { protected A getT() { return this; } }
public class B extends BBase<B> { protected B getT() { return this; } }
There's still illegal to do that:
A a = new A(); B b = new B(); a = b;
But the following is legal now:
ABase<?> a = new A(); BBase<?> b = new B(); a = b;
(Using A and B as a names for the abstract base classes, and e.g. AImpl and BImpl for a concrete implementations' names appears more convenient for me in that extended "pattern". Consider that if you'll decide to use it.)
piotr
Mike Schilling - 08 May 2007 08:02 GMT > Hi, > [quoted text clipped - 18 lines] > > new B().cool().anotherFunction(); You can do something similar with a static method, but I don't know any way to use generics to define an instance method that does what you want.
class A { static<T extends A> T cool(T t) { t.whateverYouWant(); return t; } }
Richard Reynolds - 08 May 2007 22:34 GMT > Hi, > [quoted text clipped - 22 lines] > > Aaron Fude how about this?
abstract public class A {
public A cool() {
System.out.println("A cool");
return this;
}
abstract public void anotherFunction();
public static void main(String args[]){
new B().cool().anotherFunction();
}
}
public class B extends A {
public void anotherFunction() {
System.out.println("B cool");
}
}
Lew - 09 May 2007 00:33 GMT > how about this? > [quoted text clipped - 17 lines] > > } It is a Bad Thing to hard-code knowledge of a subclass in a supertype.
 Signature Lew
Daniel Pitts - 09 May 2007 02:34 GMT > > how about this? > [quoted text clipped - 22 lines] > -- > Lew No, its not. Think of the Type Safe enum pattern. Think of the factory pattern. Its a bad thing to hard code conditional logic around the subclass in a super type. Its a good thing to use polymorphism correctly.
Lew - 09 May 2007 02:54 GMT >>> how about this? >>> abstract public class A { [quoted text clipped - 14 lines] > No, its not. > Think of the Type Safe enum pattern. Which does not get subclassed, so that does not apply.
> Think of the factory pattern. The factory knows about the subclasses; the supertype does not.
> Its a bad thing to hard code conditional logic around the subclass in > a super type. Its a good thing to use polymorphism correctly. The cited code is not an example of the correct use of polymorphism, or of any use of polymorphism.
Polymorphism would have A only know about A, but have the behavior delegate to a subclass at runtime. Having subtypes hard coded into a supertype runs against the idea of polymorphism.
 Signature Lew
Andreas Leitgeb - 09 May 2007 17:06 GMT >>>> abstract public class A { >>>> public A cool() { [quoted text clipped - 7 lines] >>>> } >>> It is a Bad Thing to hard-code knowledge of a subclass in a supertype. and
> The cited code is not an example of the correct use of polymorphism, > or of any use of polymorphism. Why not? What's so bad about having an abstract method?
The only thing that could be critizized is the use of "B" in "A"'s main method, but that's moot. (could just as well be moved to B's main method)
> Polymorphism would have A only know about A, but have the behavior > delegate to a subclass at runtime. Having subtypes hard coded into > a supertype runs against the idea of polymorphism. Exectly this seems to be the case in the cited example.
Lew - 10 May 2007 03:29 GMT >>>>> abstract public class A { >>>>> public A cool() { [quoted text clipped - 12 lines] > > Why not? What's so bad about having an abstract method? Nothing, and I never said there was. I said it was bad to hard-code a reference to s subclass in the superclass. How in the world did you get from that to an objection to use of an abstract method?
I was referring to the call to "new B()".
> The only thing that could be critizized is the use of "B" in > "A"'s main method, but that's moot. (could just as well be > moved to B's main method) Thank you. That is what I was criticizing, and what I was suggesting. It is not only not moot, it's the very point. Except that I said it *should* be moved to B's main().
 Signature Lew
Mike Schilling - 09 May 2007 05:35 GMT >> how about this? >> [quoted text clipped - 19 lines] > > It is a Bad Thing to hard-code knowledge of a subclass in a supertype. But he's not doing that except in the main() method, which isn't part of the pattern; it's simply there as a demonstration that the pattern works.
Lew - 09 May 2007 14:08 GMT >>> how about this? >>> [quoted text clipped - 21 lines] > But he's not doing that except in the main() method, which isn't part of the > pattern; it's simply there as a demonstration that the pattern works. The main should have been in the child class, then.
It isn't an excuse to put the reference in a static method. It's still a Bad Thing.
 Signature Lew
Richard Reynolds - 09 May 2007 20:29 GMT >>>> how about this? >>>> [quoted text clipped - 26 lines] > It isn't an excuse to put the reference in a static method. It's still a > Bad Thing. You can put the main wherever you want, it's only there to demo that the thing works to the OP, of course you wouldn't put it in that class for real!
Lew - 10 May 2007 03:31 GMT "Lew" wrote
>> It isn't an excuse to put the reference in a static method. It's still a >> Bad Thing.
> You can put the main wherever you want, it's only there to demo that the > thing works to the OP, of course you wouldn't put it in that class for real! If you "of course" wouldn't put it there for real, then you realize, too, that it's a Bad Thing. I was just pointing that minor point out so that people wouldn't think it was a Good Thing.
If one shouldn't do something for "real", then you shouldn't do it for "practice" either. You do what you practice, so practice what you should do.
 Signature Lew
Richard Reynolds - 10 May 2007 20:11 GMT > "Lew" wrote >>> It isn't an excuse to put the reference in a static method. It's still [quoted text clipped - 11 lines] > "practice" either. You do what you practice, so practice what you should > do. It wasn't practice, it was a demonstration of a solution to the OPs question. The solution, not the usenet demo of it, is what is important.
You completely ignored that this was a perfectly valid solution to the OPs original question and jumped on this issue. It would have been fair enough to point out to him that "of course you shouldn't put the main in there" but I imagine that a lot of people reading your responses would have thought that you were saying that the solution itself was flawed when it isn't, as borne out by some of the replies to your post.
The OP wanted a function that returns a derived class, which I displayed a way of doing.
Mike Schilling - 09 May 2007 21:16 GMT >>>> how about this? >>>> [quoted text clipped - 26 lines] > It isn't an excuse to put the reference in a static method. It's still a > Bad Thing. Sorry, I think you're being far too picky for a 20-line Usenet example.
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|