Solved

Returning a generic type

Posted on 2008-06-22
15
208 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
  • 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
Networking for the Cloud Era

Join Microsoft and Riverbed for a discussion and demonstration of enhancements to SteelConnect:
-One-click orchestration and cloud connectivity in Azure environments
-Tight integration of SD-WAN and WAN optimization capabilities
-Scalability and resiliency equal to a data center

 
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

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
oracle 11g 23 107
String array comparison 4 38
CSV file parsing thru Java 13 34
Java basic valueOf question 1 29
For beginner Java programmers or at least those new to the Eclipse IDE, the following tutorial will show some (four) ways in which you can import your Java projects to your Eclipse workbench. Introduction While learning Java can be done with…
By the end of 1980s, object oriented programming using languages like C++, Simula69 and ObjectPascal gained momentum. It looked like programmers finally found the perfect language. C++ successfully combined the object oriented principles of Simula w…
Video by: Michael
Viewers learn about how to reduce the potential repetitiveness of coding in main by developing methods to perform specific tasks for their program. Additionally, objects are introduced for the purpose of learning how to call methods in Java. Define …
Viewers will learn one way to get user input in Java. Introduce the Scanner object: Declare the variable that stores the user input: An example prompting the user for input: Methods you need to invoke in order to properly get  user input:

828 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