Solved

Returning a generic type

Posted on 2008-06-22
15
207 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
Best Practices: Disaster Recovery Testing

Besides backup, any IT division should have a disaster recovery plan. You will find a few tips below relating to the development of such a plan and to what issues one should pay special attention in the course of backup planning.

 
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

ScreenConnect 6.0 Free Trial

Explore all the enhancements in one game-changing release, ScreenConnect 6.0, based on partner feedback. New features include a redesigned UI, app configurations and chat acknowledgement to improve customer engagement!

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Python Assistance 7 80
Java JRE greater than 1.6 5 62
CSV file parsing thru Java 13 31
Glassfish admin console not working 1 12
For customizing the look of your lightweight component and making it look opaque like it was made of plastic.  This tip assumes your component to be of rectangular shape and completely opaque.   (CODE)
INTRODUCTION Working with files is a moderately common task in Java.  For most projects hard coding the file names, using parameters in configuration files, or using command-line arguments is sufficient.   However, when your application has vi…
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:
This tutorial explains how to use the VisualVM tool for the Java platform application. This video goes into detail on the Threads, Sampler, and Profiler tabs.

770 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