Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / May 2007

Tip: Looking for answers? Try searching our database.

Function that returns derived class?

Thread view: 
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 Magazines

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

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.