Solved

Returning a generic type

Posted on 2008-06-22
15
210 Views
Last Modified: 2010-03-30
Hi,

I have the following two classes defined in separate files:

public abstract class Barn<TAnimal extends Animal>
{
    public abstract TAnimal createNewAnimal();
}


public class MyBarn extends Barn<TAnimal extends Animal>
{
    public TAnimal createNewAnimal()
    {
        return new Horse();  // Horse extends Animal.
    }
}


Now the above gives me an error about not being able to convert a Horse to a TAnimal. I can just change it to this:

    return (TAnimal)(new Horse());

and it will compile but give me a type check safety warning. Is there some other way to do it to get rid of the warning? Everything makes sense to me, ie. all the classes derive properly to, in my mind, work as expected (though that really is irrelvant!),

Thanks
0
Comment
Question by:DJ_AM_Juicebox
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 3
  • 3
  • +1
15 Comments
 
LVL 13

Accepted Solution

by:
Bart Cremers earned 250 total points
ID: 21842085

class MyBarn extends Barn<Horse> {
    public Horse createNewAnimal() {
        return new Horse();  // Horse extends Animal.
    }
}

Open in new window

0
 
LVL 86

Expert Comment

by:CEHJ
ID: 21842165
>>// Horse extends Animal.

It would have to extend TAnimal
0
 

Author Comment

by:DJ_AM_Juicebox
ID: 21842345
Ok if I do this:

    class MyBarn extends Barn<Horse> {
        public Horse createNewAnimal() {
            return new Horse();  // Horse extends Animal.
        }
    }

then I lose the meaning of MyBarn still being a generic Barn, in that it only works with a Horse now, right?

Is there some way to create a factory class that can supply instance of TAnimals? I want the derived class to be able to implement it something like:

    public TAnimal createNewAnimal()
    {
          if (whatever) {
              return new Horse();
          }
          else if (whatever) {
              return new Cow();
          }
          else {
              return new Goat();
          }
    }


>> It would have to extend TAnimal
Is that possible to do? TAnimal is just saying it's some type that extends Animal (which Horse does), but how would I make Horse extend TAnimal?

Thanks
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 86

Assisted Solution

by:CEHJ
CEHJ earned 250 total points
ID: 21842410
>>Is that possible to do?

Yes.

class Horse extends TAnimal {}

>>Is there some way to create a factory class that can supply instance of TAnimals?

Yes. Given the above, the below works fine for me, returning a random TAnimal:
        public TAnimal createAnimal() {
                int ix = (int) (Math.random() * 3);
 
                switch (ix) {
                case 0:
                        return new Horse();
 
                case 1:
                        return new Cow();
 
                case 2:
                        return new Goat();
 
                default:
                        return null;
                }
        }

Open in new window

0
 

Author Comment

by:DJ_AM_Juicebox
ID: 21842418
Ok but TAnimal is just a name for some generic type which derives from Animal (if I understand correctly).

So if I have a separate source file for Horse, Cow, Goat, how will they know what a TAnimal is to derive from it, when it's only defined in the Barn source files like:

    public abstract class Barn<TAnimal extends Animal>

I could just as well call it:

    <TBeastOfBurden extends Animal>

because it doesn't really represent some actual class I thought?

Thanks
0
 
LVL 13

Expert Comment

by:Bart Cremers
ID: 21842419
Why do you need generics for that?

class AnimalFactory {
    public Animal createNewAnimal() {
        if (whatever) {
            return new Horse();
        } else if (!whatever) {
            return new Cow();
        } else {
            return new Goat();
        }
    }
}

Open in new window

0
 

Author Comment

by:DJ_AM_Juicebox
ID: 21842443
>> Why do you need generics for that?

I guess because the base class Barn keeps an array of TAnimal like:

    public abstract class Barn<TAnimal extends Animal>
    {
       protected ArrayList<TAnimal> m_animals;
    }

so if I want to add a new animal to that array, it needs to be a TAnimal, not just an Animal?

Thanks
0
 
LVL 13

Expert Comment

by:Bart Cremers
ID: 21842483
I understand why you would go for a generic TAnimal in you barn class so you can make sure it are all Horses or all Goats. But there's no need to use generics in the way you want (it's even not possible) if you want to mix animals anyway.

Either you go for generics and use my first example (a specific horse barn, ...) or you drop generics (for creation) and make a factory capable of returning any animal.
0
 
LVL 92

Expert Comment

by:objects
ID: 21842615
I agree with Bart_Cr and would use a factory, but have different factory instances foir different type

eg.

public class HorseFactory extends AnimalFactory
{
   public TAnimnal createAnimal()
   {
       return new Horse();
   }
}

0
 

Author Comment

by:DJ_AM_Juicebox
ID: 21842638
Ok I see what you mean, I think my initial example is slightly off what I really want, so it's now not making any sense. I think the answers given were very helpful, I'm going to close this question and start a new one with a better example to avoid confusion,

Thanks
0
 
LVL 92

Expert Comment

by:objects
ID: 21842678
What you want to avoid is using an if/swicth to create your instance, thats poor programming practice.
0
 

Author Comment

by:DJ_AM_Juicebox
ID: 21842691
@ objects

Sorry I closed the question while you were posting this:

public class HorseFactory extends AnimalFactory
{
   public TAnimnal createAnimal()
   {
       return new Horse();
   }
}

I don't understand how HorseFactory knows what a TAnimal is though?
0
 
LVL 92

Expert Comment

by:objects
ID: 21842705
sorry that was a typo, should have been

   public Animal createAnimal()

And would have a variety of different Factory implementations that met your needs. Avoiding the need for a messy switch statement.

If this help, I can get the q reopened for you.

0
 

Author Comment

by:DJ_AM_Juicebox
ID: 21842707
It's ok, I just wrote this into another question which I'm gonna open in a minute,

Thanks
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 21844454
:-)
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This was posted to the Netbeans forum a Feb, 2010 and I also sent it to Verisign. Who didn't help much in my struggles to get my application signed. ------------------------- Start The idea here is to target your cell phones with the correct…
Java Flight Recorder and Java Mission Control together create a complete tool chain to continuously collect low level and detailed runtime information enabling after-the-fact incident analysis. Java Flight Recorder is a profiling and event collectio…
This tutorial covers a practical example of lazy loading technique and early loading technique in a Singleton Design Pattern.
This video teaches viewers about errors in exception handling.

734 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question