为什么派生类重写方法不应该比java.lang中的基类更具限制性为什么编译器会抛出错误?你能请任何人解释原因吗?为什么派生类重写方法不应该比java中的基类更具限制性?
回答
的一点是,谁只知道你的超主叫用户应该仍然能够使用子是它给的任何实例。考虑这种情况:从不同的包
public class Super
{
public void print()
{
System.out.println("Hello!");
}
}
public class Sub extends Super
{
@Override
void print() // Invalid
{
System.out.println("Package access");
}
}
现在,假设我们有:
public void printSuper(Super x)
{
x.print();
}
我们叫随:
printSuper(new Sub());
你会想到做什么?你覆盖方法,所以它应该打印“包访问” - 但是那意味着你调用从不同的封装包访问方法...
基本上,这是的只是一个例子Liskov Substitution Principle正在进行中。您应该能够将任何子类的实例作为超类的实例对待,并且很难看出它是如何适合于使子类更具限制性的。
您不能使访问修饰符更具限制性,因为这会违反继承的基本规则,即子类实例应该可替换而不是超类实例。
对于例如 假设人类具有的getName正在使用由许多类(包括非子类),但有人刚添加雇员作为人的子类,并的getName在公共方法 员工受保护应该只能通过子类访问,那么以前的代码将开始打破,员工将不能替换为Person对象。
因此,java已决定实施这种重构。
考虑例如
class Mammal {
public Mammal readAndGet() throws IOException {//read file and return Mammal`s object}
}
class Human extends Mammal {
@Override
public Human readAndGet() throws FileNotFoundException {//read file and return Human object}
}
下方,如果我们执行下面的代码
Mammal mammal = new Human();
Mammal obj = mammal.readAndGet();
而且我们知道,编译器mammal.readAndGet()
正从Mammal
类的对象,但在调用,运行时JVM将解决mammal.readAndGet()
方法呼叫来自类Human
的呼叫,因为mammal
持有new Human()
。
方法readAndGet
在Mammal
定义公共和以使其在Human
类的限制较少,我们将需要要么删除访问符(使它default
)或使其protected
或private
。
现在假设
- 如果我们定义
readAndGet
为default
或Human
但Human
protected
在另一个包 - 定义。如果我们在人的定义
readAndGet
私人
我们知道JVM会在运行时解决方法调用,但编译器不知道这一点,在这两种情况下,公司de会编译成功,因为编译器readAndGet
正在从类Mammal
中调用。
但在这两种情况下,在运行时JVM将无法从人类获得readAndGet
,因为这将限制因Human
类的readAndGet
严格的访问。
而且我们还不能确定谁将在未来扩展我们的类,以及他将在哪些包中执行该操作,如果该人使重写方法的限制性更小,那么JVM可能无法调用方法和代码将在运行时中断。
所以为了避免这种不确定性,根本不允许在子类中分配对重写方法的限制访问。
还有其他规则,我们需要遵循,同时覆盖的方法,你可以阅读更多的Why We Should Follow Method Overriding Rules知道原因。
- 1. 如果派生类重写方法,为什么调用基类方法?
- 2. 为什么我们只能访问A类方法。为什么重写方法不能更具限制性?
- 3. 调用重写的方法在派生类的基类
- 4. 重写基类的常量方法从派生类
- 5. Java继承 - 在派生对象中使用基本变量时,派生类重写基类方法
- 6. Python:找出派生类称为基类方法的什么方法
- 7. 为什么'virtual'对于派生类中的重写方法是可选的?
- 8. C#:我的派生类无法重写基类的接口方法实现,为什么?
- 9. 在C#中如何调用派生类实例中已在派生类中重写的基类方法
- 10. Java:在不同返回类型的派生类中重写方法?
- 11. 派生类不继承基类的重载方法
- 12. 派生的方法在基类不叫
- 13. 为什么基类私有属性被派生类访问?
- 14. Python的超:调用它包含由派生类中重写另一个基类方法的基类方法
- 15. Java;将基类转换为派生类
- 16. 哪个基类调用派生重写方法?
- 17. 我应该添加DataMember属性来重写派生类中的属性吗?
- 18. 为什么派生类不能引用基类?
- 19. 在派生类的方法中使用基类的方法
- 20. 将模板函数限制为基类和派生类型?
- 21. 从基类访问应用于派生类中的方法的属性
- 22. 抽象类的需求是什么?为什么通过其基类访问派生类方法?在C++中
- 23. Java:派生类中的方法链接
- 24. 限制传递派生类的实例作为方法参数
- 25. 为什么要将基类中的受保护访问更改为派生类中的公共访问权限?
- 26. 定义派生类时,为什么基类标记为“公共”?
- 27. 派生类使用基类的属性?
- 28. 基类中的Ruby访问派生类“类方法”
- 29. 使用在基类派生类,而派生类的基类
- 30. 在python中派生类方法的正确方法是什么?
为什么要这样呢?显示一些代码。 – 2013-04-24 06:27:19
对于初学者来说,这是一个完全有效的问题。我真的不明白为什么应该关闭。 – helpermethod 2013-04-24 09:14:26