当前位置: 首页 > 知识库问答 >
问题:

重写具有抽象基类参数的方法

澹台成龙
2023-03-14

所以,问题是:我有一个抽象基类(property),它有一个抽象成员方法(same())。same()方法返回布尔值,并应检查是否相等,但“相等”在子类中可能有不同的解释,因此我不重写equals()compareTo()。因为它测试是否与另一个与其类型相同的对象相等,所以签名如下所示:

public abstract boolean same(Property other);

现在,当我试图在类中重写它时,假设“subproperty”,我不能使用subproperty作为参数的类型。我知道一般情况下这样做的原因和添加类型界限的建议,但是事情变得更加复杂,因为参数类型是它自己的类。

有没有什么平滑的方法可以正确地重写方法?

因为在其他StackOverflow问题中推荐了它,所以我尝试使用类型界限(在本例中是循环的)。因此,类将如下所示:

public abstract class Property<T extends Property<T>>

same()方法:

public abstract boolean same(T other);
public class SubProperty extends Property<SubProperty>

same()方法:

public boolean same(SubProperty other);

如果我按照建议使用类型界限,就会出现这样的结果。它真的在建造,但我甚至不知道它是否能正常工作。无论如何,它看起来很可怕,而且不可维护(特别是因为我在property中使用了另外2个泛型类型参数)。

我希望有其他方法可以做到这一点。如果重要的话,我使用的是Java1.8(openjdk 1.8.0.212-B04)

因为人们问:same()不像equals()compareto()。是的,它在某种意义上讲是关于平等的。但其实我觉得这样描述更容易:

same()是一个方法,用于检查this和同一类的其他对象中的某些内容,并根据方法中发生的情况返回truefalse

编辑2:

正如@davidxxx所解释的,似乎不可能让代码变得更“流畅”。我很可能只保留基类参数,然后检查我在方法中得到了哪个对象。看来还不算太糟。

共有1个答案

寿意远
2023-03-14

不幸的是,您没有其他方法,因为在Java中,返回类型是协变的,而参数类型却不是协变的,因为这与liskov原则是相反的。

利斯科夫的行为亚型概念定义了对象的可替代性概念;也就是说,如果S是T的子类型,那么程序中T类型的对象可以用S类型的对象替换,而不改变该程序的任何期望的属性(例如正确性)。

下面是一个简单的例子,说明了为什么这个规则很重要。

public class FooProperty extends Property{
    public boolean same(FooProperty other){...}
}
Property property = new FooProperty();

您可以这样做:

property.same(new FooProperty());

但您还可以执行以下操作:

property.same(new Property());

但就FooProperty.same()重写的预期参数而言,这是不一致的,重写预期的是FooProperty.
并且这违反了liskov原则,因为我应该可以将任何Property实例替换为该html" target="_blank">实例的任何子类。

只是,在类上声明的泛型类型(如您的示例中所示)允许绕过这个限制,并离开子类,决定将子类用作参数。

不管怎么说,它看起来很可怕而且无法维护

这是非常可维护性的,因为如果重构类名,它将被更新。但这确实有点冗长。

 类似资料:
  • 想象一下,我有一个抽象类动物的方法: 然后我有一个类,用以下内容扩展这个抽象类: 我希望每个扩展Animal的类都有一个fetch()方法。然而,fetch方法为相关动物指定了一些独特的特征(狗的爪子、猫的爪子等)。例如,cat的fetch()将获取参数fetch(fellinecat kitty)并表示: 因此,抓取方法接受了扩展抽象类“动物”(因此是动物)的参数。我在“动物”中定义了抓取()方

  • 我无法编译一个需要从抽象类超类型重写方法的方法,该类超类型使用泛型作为其中一个参数。编译器抱怨扩展类的setRef()方法没有重写超类型中的方法。 父摘要类: 参考是: 而Interf是: 扩展子类(setRef()不编译): 我也尝试过使用通配符,但收到了相同的错误。使用通配符时,抽象类“setRef()是: 扩展类setRef()是: 甚至: 我能让它编译的唯一方法是,如果扩展类“setRef

  • 问题内容: 当其中的所有方法都是具体的时,有人在声明类抽象时有一些实际的编程情况吗? 问题答案: 好吧,您可能正在使用模板方法模式,其中存在多个都具有默认实现的覆盖点,但是组合的默认实现本身不合法-任何功能实现都必须是子类。 (是的,我不喜欢模板方法模式;)

  • 我的类KTree正在扩展抽象类GraphClass,但无法重写GraphClass中定义的一个方法。 原始方法添加(E E,V V,V v1)在界面无向图中定义 在类中,addEdge(E E,V V,V v1)抛出错误 “KTree”中的“addEdge(E,V,V)”与“GraphClass”中的“addEdge(E,V,V)”冲突;两种方法具有相同的擦除,但都不重写另一种方法 KTree中的

  • 大家好,我有这个主课堂 错误:(42,8)错误:Home不是抽象的,并且不会覆盖OnFragmentInteractionListener中的onFragmentInteract(String)抽象方法 我创建了一个导航抽屉,并希望有一个新的片段来显示另一个家庭活动的内容。 Android Studio告诉我做个家。类抽象或实现抽象方法。 里面: 我那样做了,但是什么也没有改变。我不能让home类