所以,问题是:我有一个抽象基类(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
和同一类的其他对象中的某些内容,并根据方法中发生的情况返回true
或false
。
编辑2:
正如@davidxxx所解释的,似乎不可能让代码变得更“流畅”。我很可能只保留基类参数,然后检查我在方法中得到了哪个对象。看来还不算太糟。
不幸的是,您没有其他方法,因为在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类