我有简单的抽象结构
public abstract class Data<A extends Serializable> {
}
然后是此类的String实现
public class StringData extends Data<String> {
}
然后我有界面:
public interface Testicek<A extends Serializable> {
public abstract Data<A> test(Data<A> bla);
}
现在我要创建实现此接口的类:
public class TesticekImpl implements Testicek<String> {
// OK
@Override
public StringData test(Data<String> bla) {
return null;
}
// compilation error
//@Override
//public StringData test(StringData bla) {
// return null;
//}
}
为什么我不能将StringData类用作参数,并且只能在返回类型中使用?返回类型和参数的签名相同。
答案 0 :(得分:5)
public interface Testicek<A extends Serializable> {
public abstract Data<A> test(Data<A> bla);
}
Java允许covariant return types,这意味着接口的实现可以返回比父接口更具体的类型,因为那些更具体的类型仍然是不那么具体的类型的实例,因此它们符合界面。
但是,您不能使用更具体的参数类型,因为接口的约定规定它必须接受该类型的任何实例。
Liskov Substitution Principle告诉我们,子类必须接受不再具有限制性的参数,并且必须返回不再具有一般性的值。
由于the way it resolves methods to invoke at compile time(已经很复杂了),Java不允许您使用“限制较少”的参数类型。从理论的角度来看,这是不必要的限制,但从实践的角度来看,则更为简单。
就您接受并返回相同类型而言:在您的接口中声明另一个类型变量:
public interface Testicek<A extends Serializable, D extends Data<A>> {
public abstract D test(D bla);
}
那么您的实现可以是:
public class TesticekImpl implements Testicek<String, StringData> {
@Override
public StringData test(StringData bla) {
return null;
}
}