【问题标题】:Why I can not override method using implementation of class as parameter为什么我不能使用类的实现作为参数来覆盖方法
【发布时间】:2019-06-06 13:10:02
【问题描述】:

我有简单的抽象结构

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 类作为参数,它只适用于返回类型?返回类型和参数的签名相同。

【问题讨论】:

  • 因为您实现 Testicek 的事实要求您必须接受 Data 类型的 any 对象。 StringData 只是 Data 的无数子类型中的 一个。这还不够。您必须接受所有这些,否则您根本就没有实现接口。该接口声称它接受所有这些。您可以返回 StringData,因为您可以返回任何符合 Data 条件的内容,而 StringData 可以。
  • @kumesana 这看起来像是对我的回答。
  • 是的,但它在评论中,所以我不能接受它:P
  • 假设您有class Parent { void eat(Fruit t){..} }class Child extends Parent { @override void eat (Apple a){..} }。因为Child extends Parent 我们可以写成Parent p = new Child();。但是因为pParent 类型,它应该支持eat(Fruit),我们应该能够安全地调用p.eat(new Banana())(其中BananaFruit 的子类型,但不是subtype of Apple)。那么这里应该发生什么?应该调用哪个方法的代码?压倒对 Apples 的有限可接受的论点,但 Parent 承诺处理各种 Fruits。

标签: java generics


【解决方案1】:
public interface Testicek<A extends Serializable> {

    public abstract Data<A> test(Data<A> bla);

}

Java 允许covariant return types,这意味着接口的实现可以返回比父接口更具体的类型,因为那些更具体的类型仍然是不太具体的类型的实例,因此它们符合接口的约定.

但是,您不能使用更具体的参数类型,因为接口的合同规定它必须接受该类型的任何实例。

Liskov Substitution Principle 告诉我们,子类必须接受不再具有限制性的参数,并且必须返回不再通用的值。

Java 不允许您使用“限制较少”的参数类型,因为the way it resolves methods to invoke at compile time(这已经相当复杂了)。从理论的角度来看,这是不必要的限制,但从实践的角度来看更简单。

就你接受和返回相同类型而言:在你的界面中声明另一个类型变量:

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;
    }
}

【讨论】:

    猜你喜欢
    • 2012-07-03
    • 2018-05-02
    • 2016-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-09
    相关资源
    最近更新 更多