Function that returns derived class?

A

aaronfude

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
 
P

Piotr Kobzda

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() {

}

public B cool() {
super.cool();
return this;
}
}

And then I want the following to work

new B().cool().anotherFunction();


piotr
 
S

Spring Liu

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

((B) new B().cool()).anotherFunction();
 
A

aaronfude

Can the overriding and the casts be avoided with some kind of template
structure?

Thanks
 
M

Mike Schilling

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

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;
}
}
 
B

Ben Schumeth

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
 
P

Piotr Kobzda

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
 
H

Hendrik Maryns

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Piotr Kobzda schreef:
public B cool() {
super.cool();
return this;
}

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
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFGQEGDe+7xMGD3itQRAoVVAJ9MwwIUH82qfsPHLVafuP+tvEAnNgCfc0sm
A5z86iq8/dLZYNtF0aDEpwI=
=4Moa
-----END PGP SIGNATURE-----
 
H

Hendrik Maryns

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Piotr Kobzda schreef:
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.
I guess you meant:

public B cool() {
return (B) super.cool();
}


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
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFGQFLSe+7xMGD3itQRAsZjAJ0dMK9cCh4Ushdbu42vHh2XqCGafQCeMenN
Z9P4qQHZsjRomRuyDcjY0p8=
=JUm/
-----END PGP SIGNATURE-----
 
R

Richard Reynolds

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
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");

}

}
 
L

Lew

Richard said:
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();

}

}

It is a Bad Thing to hard-code knowledge of a subclass in a supertype.
 
D

Daniel Pitts

Richard said:
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();

}

It is a Bad Thing to hard-code knowledge of a subclass in a supertype.

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

Lew

Daniel said:
Richard said:
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();
}
}
It is a Bad Thing to hard-code knowledge of a subclass in a supertype.

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

Mike Schilling

Lew said:
Richard said:
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();

}

}

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

Lew

Mike said:
Lew said:
Richard said:
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();

}

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

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

Andreas Leitgeb

Lew said:
Richard Reynolds wrote:
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();
}
}
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.
 
R

Richard Reynolds

Lew said:
Mike said:
Lew said:
Richard Reynolds wrote:
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();

}

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

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.

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

Mike Schilling

Lew said:
Mike said:
Lew said:
Richard Reynolds wrote:
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();

}

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

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.

Sorry, I think you're being far too picky for a 20-line Usenet example.
 
L

Lew

Andreas said:
Lew said:
Richard Reynolds wrote:
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();
}
}
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?

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

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
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top