Reputation: 41
public class Role<A extends Actor> {
protected A actor;
protected A constructActor() {
return new Actor();
}
}
Why won't this Java code compile? My IDE tells me that constructActor() needs to return an A type, but not an Actor type. But as far as I understand I made it clear that A will be an Actor or an extension of an Actor. So why does Java behave this way?
Edit:
You might help me further with my idea of a "generified" factory pattern:
The constructActor() method actually wasn't intended to always return an instance of Actor (therefore the protected access), but to be some kind of default case for every child class that doesn't has to construct a specified version of the Actor:
// the first two cases should construct specified versions of the Actor
public class HeroRole<HeroActor> {
@Override protected HeroActor constructActor() {
return new HeroActor();
}
}
public class EnemyRole<EnemyActor> {
@Override protected EnemyActor constructActor() {
return new EnemyActor();
}
}
// the following classes should construct a regular Actor by default:
public class AnimalRole<Actor> {
}
public class GhostRole<Actor> {
}
The reason for the Generics is that every child class of Role knows its Actor as specified as possible to prevent casts. As you can see there are child classes of Role that need to construct specified versions of the Actor class (Hero, Enemy). But for the other classes (Animal, Ghost) I thought I could save the implementations of the constructActor() method by following my initial idea. That didn't work. Is there any other way of defining a default case in this scenario?
Upvotes: 3
Views: 98
Reputation: 393841
A
can be an Actor
or a sub-class (or sub-interface) of actor.
Suppose you write:
Role<SubActor> role = new Role<> ();
SubActor actor = role.constructActor ();
This should pass compilation (based on the definition of your Role
class and its generic type parameter A
), but your constructActor()
method always returns an Actor
, which is not always a SubActor
.
If your constructActor()
method always returns an instance of Actor
, you should just change its return type to Actor
. There is no need to use A
.
Upvotes: 2
Reputation: 1500695
But as far as I understand I made it clear that A will be an Actor or an extension of an Actor. So why does Java behave this way?
Yes, A
will be Actor
or a subclass of Actor
- but that's the wrong direction of inheritance for what you want.
Suppose we have a Role<SpecialistActor>
. Then constructActor()
should return a SpecialistActor
... and while a SpecialistActor
is an Actor
, a plain Actor
(as in the result of new Actor()
) is not a SpecialistActor
. It's like trying to return a reference to an instance of Object
in a method that is declared to return String
:
public String constructString() {
return new Object();
}
You wouldn't expect that to compile, right? So apply the same reasoning to your example.
Upvotes: 7