让我们说你有这个课程:
import java.util.ArrayList;
public class Array
{
private ArrayList<Object> a = new ArrayList<Object>();
public void add(Object element)
{
a.add(element);
}
public void addAll(Object elements[])
{
for (int i = 0; i < elements.length; ++i)
a.add(elements[i]); // this line is going to be changed
}
}
这个派生类:
public class ArrayCount extends Array
{
private int count = 0;
@Override
public void add(Object element)
{
super.add(element);
++count;
}
@Override
public void addAll(Object elements[])
{
super.addAll(elements);
count += elements.length;
}
}
如果在基类中,我们进行以下更改:
public void addAll(Object elements[])
{
for (int i = 0; i < elements.length; ++i)
add(elements[i]); // this line was changed
}
我希望调用基类中的add()方法,而不是派生类中重写的add()。为什么不是这样?这个例子是滥用OOP吗?
答案 0 :(得分:2)
Java将始终调用运行时类的方法实现(运行时的真实对象类),只要它是有效的方法覆盖。这称为动态绑定。
你没有滥用,而是利用有保证的功能。
你所拥有的设计在Java中是合法的,但出于多种原因这是一种不好的做法,你突出了一个重要的原因。这是有时不鼓励实现继承的主要原因之一,支持接口继承。
答案 1 :(得分:0)
在一天结束时,它归结为运行时发生的事情。
由于函数是add()
,它将调用add()
this
对象,这是在运行时被覆盖的函数。
这是封装的全部要点,子类应该完全控制其方法的作用。
答案 2 :(得分:0)
我希望调用基类中的add()方法,而不是派生类中重写的add()。为什么不是这样?
Java使用动态分派(也称为动态绑定)在运行时绑定方法。简单来说,这意味着当在基类上调用方法时,执行的方法是对象的实际类型。请参阅Wikipedia article或Java reference on polymorphism。
此示例是滥用OOP吗?
对于一个展示动态调度的人为例子,它并不坏。对于其他任何事情,这都是毫无意义的。
答案 3 :(得分:-1)
我认为以下更改可以解决问题:
如果在基类中,我们进行以下更改:
public void addAll(Object elements[])
{
for (int i = 0; i < elements.length; ++i)
super.add(elements[i]); // <-- new use of SUPER
}
基本上,如果您希望某些方法不变(总是做同样的事情),您必须声明它们final
以防止覆盖。否则,派生类可以实现他们想要的任何东西。
(的修复是编写文档,解释任何派生方法必须遵循的合同。)