假设我有一些课
public class Foo {
public void foo(int number) {
// Do some foo-ing of the given number
}
}
和另一个扩展它的类
public class FooExtension extends Foo {
public void foo(String text) {
super.foo(text.length());
}
}
让我们说如果您使用的是FooExtension
对象,那么您真的不应该调用foo(int number)
方法,而应该只使用foo(String text)
。
由于在我将foo(int number)
实例分配给FooExtension
变量时违反了合同,因此无法覆盖原始类的Foo
方法,因为该方法具有较低的可见性。
有没有一种方法被认为是“良好做法”,表明如果您使用的是FooExtension
,那么您真的不应该再调用foo
的原始版本了吗?也许压倒它并标记它已被弃用?或者覆盖它并让它抛出UnsupportedOperationException
?
答案 0 :(得分:2)
有没有一种方法被认为是“良好做法”,表明如果你使用的是FooExtension,你真的不应该再调用原始版本的foo了吗?也许压倒它并标记它已被弃用?或者覆盖它并让它抛出UnsupportedOperationException?
当你开始采用“不良做法”时,很难定义一个“良好做法”。如果您继承自某个类,但不想要父类的某些方法,那么您根本不应该使用继承!
有可能吗?是的,可以做你想做的事:
public class FooExtension extends Foo {
@Override
public void foo(int number) {
throw new UsupportedOperationException("Operation is not supported");
}
public void foo(String text) {
super.foo(text.length());
}
}
但我觉得设计这样的东西很糟糕。如果他们试图调用属于超类型的方法并获得异常,则代码的用户可能会感到惊讶。
在这种情况下,使用组合而不是继承更好。这样,您只需将仅所需的调用委托给内部实例。
修改强>
公共继承是一种“是一种”关系。因此,从使用您的课程的人的角度来看,他们希望FooExtension
的行为类似于Foo
,除了一些额外的行为。通过做你正在做的事情,你违反了这个定义。
您的设计违反的另一件事是Liskov substitution principle。原则说如果你有类型S
的子类型T
,那么用T
类型的对象替换类型S
的对象不应该改变你的程序的行为
如果要遵循您的设计,将Foo
的实例替换为FooExtension
将导致您的程序失败。这就是为什么你不想做的事情。
答案 1 :(得分:0)
这不是覆盖。这是一个过载。如果重载方法在基类中,则重载会隐藏它们重载的方法。这是Java和C ++的基本规则。
因此,您的问题的答案已经发生。