Function that returns derived class?

Discussion in 'Java' started by aaronfude@gmail.com, May 7, 2007.

  1. Guest

    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
    , May 7, 2007
    #1
    1. Advertising

  2. Piotr Kobzda Guest

    wrote:

    > 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
    Piotr Kobzda, May 7, 2007
    #2
    1. Advertising

  3. Spring Liu Guest

    On May 8, 6:23 am, wrote:
    > 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();
    Spring Liu, May 8, 2007
    #3
  4. Guest

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

    Thanks
    On May 7, 7:41 pm, Spring Liu <> wrote:
    > On May 8, 6:23 am, wrote:
    >
    >
    >
    >
    >
    > > 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();- Hide quoted text -
    >
    > - Show quoted text -
    , May 8, 2007
    #4
  5. <> wrote in message
    news:...
    > 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;
    }
    }
    Mike Schilling, May 8, 2007
    #5
  6. Ben Schumeth Guest

    On Tue, 08 May 2007 02:41:36 +0200, <> wrote:

    > 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

    --
    Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
    Ben Schumeth, May 8, 2007
    #6
  7. Piotr Kobzda Guest

    wrote:

    > 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
    Piotr Kobzda, May 8, 2007
    #7
  8. -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA1

    Piotr Kobzda schreef:
    > wrote:
    >
    >> 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;
    > }
    >
    >> }


    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-----
    Hendrik Maryns, May 8, 2007
    #8
  9. Piotr Kobzda Guest

    Hendrik Maryns wrote:
    > 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
    Piotr Kobzda, May 8, 2007
    #9
  10. -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA1

    Piotr Kobzda schreef:
    > Hendrik Maryns wrote:
    >> 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.


    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.

    >
    > 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-----
    Hendrik Maryns, May 8, 2007
    #10
  11. <> wrote in message
    news:...
    > 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");

    }

    }
    Richard Reynolds, May 8, 2007
    #11
  12. Lew Guest

    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.


    --
    Lew
    Lew, May 9, 2007
    #12
  13. Daniel Pitts Guest

    On May 8, 4:33 pm, Lew <> wrote:
    > 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.
    >
    > --
    > 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.
    Daniel Pitts, May 9, 2007
    #13
  14. Lew Guest

    Daniel Pitts wrote:
    > On May 8, 4:33 pm, Lew <> wrote:
    >> 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.
    >>
    >> --
    >> Lew

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

    --
    Lew
    Lew, May 9, 2007
    #14
  15. "Lew" <> wrote in message
    news:...
    > 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.
    Mike Schilling, May 9, 2007
    #15
  16. Lew Guest

    Mike Schilling wrote:
    > "Lew" <> wrote in message
    > news:...
    >> 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.

    --
    Lew
    Lew, May 9, 2007
    #16
  17. Lew <> wrote:
    >>> 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.
    Andreas Leitgeb, May 9, 2007
    #17
  18. "Lew" <> wrote in message
    news:...
    > Mike Schilling wrote:
    >> "Lew" <> wrote in message
    >> news:...
    >>> 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.
    >
    > --
    > Lew


    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!
    Richard Reynolds, May 9, 2007
    #18
  19. "Lew" <> wrote in message
    news:...
    > Mike Schilling wrote:
    >> "Lew" <> wrote in message
    >> news:...
    >>> 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.
    Mike Schilling, May 9, 2007
    #19
  20. Lew Guest

    Andreas Leitgeb wrote:
    > Lew <> wrote:
    >>>> 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().

    --
    Lew
    Lew, May 10, 2007
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Teis Draiby
    Replies:
    3
    Views:
    449
    Pete Vidler
    Apr 2, 2004
  2. Replies:
    1
    Views:
    394
    myork
    May 23, 2007
  3. Replies:
    1
    Views:
    386
    Victor Bazarov
    May 23, 2007
  4. George2
    Replies:
    0
    Views:
    350
    George2
    Mar 17, 2008
  5. Lionel B
    Replies:
    8
    Views:
    337
    James Kanze
    Feb 5, 2009
Loading...

Share This Page