Solved

Returning a generic type

Posted on 2008-06-22
15
204 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_Cr earned 250 total points
Comment Utility

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
Comment Utility
>>// Horse extends Animal.

It would have to extend TAnimal
0
 

Author Comment

by:DJ_AM_Juicebox
Comment Utility
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
 
LVL 86

Assisted Solution

by:CEHJ
CEHJ earned 250 total points
Comment Utility
>>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
Comment Utility
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_Cr
Comment Utility
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
Comment Utility
>> 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
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 
LVL 13

Expert Comment

by:Bart_Cr
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
@ 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
Comment Utility
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
Comment Utility
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
Comment Utility
:-)
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

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…
In this post we will learn how to connect and configure Android Device (Smartphone etc.) with Android Studio. After that we will run a simple Hello World Program.
Viewers learn about the “while” loop and how to utilize it correctly in Java. Additionally, viewers begin exploring how to include conditional statements within a while loop and avoid an endless loop. Define While Loop: Basic Example: Explanatio…
Viewers will learn about the regular for loop in Java and how to use it. Definition: Break the for loop down into 3 parts: Syntax when using for loops: Example using a for loop:

744 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

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now