I have a base class that has an abstract getType() method. I want subclasses to be able to implement this method and provide the actual class to use.
In code, something like the following:
public abstract class A {
public static interface Tile;
protected abstract Class<Tile> getTileClass();
}
public class B extends A {
public static class MyTile implements A.Tile { }
@Override
protected abstract Class<A.Tile> getTileClass() {
MyTile t = new MyTile(); // WORKS
return MyTile; // ERROR HERE
}
}
The problem here is that I get "MyTile cannot be resolved" in the line marked. So I'm trying to return this instead:
return new MyTile().getClass()
but now Eclipse tells me:
Type mismatch: cannot convert from Class
<
capture#1-of ? extends B.MyTile>
to Class<
A.Tile>
which I'm not even sure if there's maybe a bug in Eclipse here top (capture#1?).
Next, I'm giving up on interfaces and trying to use an abstract base Tile class. With some help from Eclipse, I end up with the following code that seems to compile:
public abstract class A {
public static abstract class Tile;
protected abstract Class<? extends Tile> getTileClass();
}
public class B extends A {
public static class MyTile exends A.Tile { }
@Override
protected abstract Class<? extends A.Tile> getTileClass() {
return new MyTile().getClass(); // WORKS
return MyTile; // "Cannot be resolved"
}
}
So I basically seem to have three questions:
1) Is it possible to get this to work with A.Tile being an interface?
2) When using a base class, is Class<? extends X>
really the correct way to go?
3) And how can I return my nested B.MyTile class reference from inside the method? Having to do new MyTile().getClass()
can't be right, can it?
Generics and covariant type overriding do not work very well together. You have to explicitly declare getTileClass() as returning a class that can be a subclass of A.Tile.
You also can access the class object of MyTile without instanciating it, with MyTile.class.
Try this instead:
public abstract class A {
public static interface Tile;
protected abstract Class<? extends Tile> getTileClass();
}
public class B extends A {
public static class MyTile implements A.Tile { }
@Override
protected Class<MyTile> getTileClass() {
return MyTile.class;
}
}
Even better would be to make A generic. You still have to use extends in the class type definition, but you can be a bit more specific:
public abstract class A<T extends A.Tile> {
public static interface Tile;
protected abstract Class<? extends T> getTileClass();
}
public class B extends A {
public static class MyTile implements A.Tile { }
@Override
protected Class<MyTile> getTileClass() {
return MyTile.class;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With