I'm new to using bounded types in Java, and I'm not sure if the following is a programming error because of a bad use of inheritance or a javac bug
I need to define two different type of objects: things which have to be managed and managers of that things. That's why I created an abstract class to model the common behavior of those things
public abstract class AbstractThing {
// Common method implemented
public void hello() {
System.out.println("HI, I'm AbstractThing");
}
}
and an interface to define the methods that those things' manager must implement
public interface AbstractManager {
// Operation that a things' manager must implement
public <T extends AbstractThing> void greet(T t);
}
So suppose I create two concrete things classes, one of them just inherits the abstract one:
public class Thing extends AbstractThing {
// Constructor
public Thing() {}
}
but the other one implements an own method:
public class AnotherThing extends AbstractThing {
// Constructor
public AnotherThing() {}
// Extra method which this class implements
public void goodbye() {
System.out.println("BYE, I'm AnotherThing");
}
}
But when I define a manager as follows:
public class Manager implements AbstractManager {
// Constructor method
public Manager() {}
// Implementation of the interface's method fails
@Override
public <AnotherThing extends AbstractThing>
void greet(AnotherThing t) {
// I can use this method, which AnotherThing inherits from AbstractThing
t.hello();
// But I can't use this one defined by AnotherThing
t.goodbye();
}
}
I get the error:
AnotherManager.java:15: error: cannot find symbol
t.goodbye();
^
symbol: method goodbye()
location: variable t of type AnotherThing
where AnotherThing is a type-variable:
AnotherThing extends AbstractThing declared in method <AnotherThing>greet(AnotherThing)
1 error
And I don't understand why, because it's recognizing the class as AnotherThing, but it's dealing it as AbstractThing. I've tried to cast the object as the subclass, but it doesn't work
I've also checked that it only happens when I try to access the subtype methods, because the following manager compile and works perfectly:
public class Manager implements AbstractManager {
// Constructor method
public Manager() {}
// Implementation of the method defined into the interface
@Override
public <Thing extends AbstractThing>
void greet(Thing t) {
t.hello();
}
// I can overload the method "greet" without overriding the interface
// and it works for AnotherThing
public void greet(AnotherThing t) {
t.hello();
t.goodbye();
}
}
Any idea about what's happening there?
Here's why
It's not difficult to figure out if you do something like this
In other words, the word before the "extends" is not supposed to be a class name, but a generic identifier (a variable name).
In this case, since T (or wharever you call it) is AbstractThing, it does not know what goodbye() is.
Now, why your last example works?
Because you're saying that greet receives a object of type AnotherThing, not a generic type such as T.