• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 220
  • Last Modified:

Returning a generic type

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
DJ_AM_Juicebox
Asked:
DJ_AM_Juicebox
  • 6
  • 3
  • 3
  • +1
2 Solutions
 
Bart CremersJava ArchitectCommented:

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

Open in new window

0
 
CEHJCommented:
>>// Horse extends Animal.

It would have to extend TAnimal
0
 
DJ_AM_JuiceboxAuthor Commented:
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
Cloud Class® Course: CompTIA Healthcare IT Tech

This course will help prep you to earn the CompTIA Healthcare IT Technician certification showing that you have the knowledge and skills needed to succeed in installing, managing, and troubleshooting IT systems in medical and clinical settings.

 
CEHJCommented:
>>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
 
DJ_AM_JuiceboxAuthor Commented:
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
 
Bart CremersJava ArchitectCommented:
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
 
DJ_AM_JuiceboxAuthor Commented:
>> 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
 
Bart CremersJava ArchitectCommented:
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
 
objectsCommented:
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
 
DJ_AM_JuiceboxAuthor Commented:
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
 
objectsCommented:
What you want to avoid is using an if/swicth to create your instance, thats poor programming practice.
0
 
DJ_AM_JuiceboxAuthor Commented:
@ 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
 
objectsCommented:
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
 
DJ_AM_JuiceboxAuthor Commented:
It's ok, I just wrote this into another question which I'm gonna open in a minute,

Thanks
0
 
CEHJCommented:
:-)
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

  • 6
  • 3
  • 3
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now