为什么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());
你觉得这样做会有什么效果呢?由于你正在覆盖方法,所以它应该打印出“包访问权限”,但这意味着你正在从不同的包中调用一个包访问权限方法...
基本上,这只是里氏替换原则在实践中的一个例子。你应该能够将任何子类的实例视为超类的实例,很难看出如何将其与在子类中变得更加严格相结合。
访问修饰符不能更加严格,因为这会违反继承的基本规则:子类实例应该能够替换超类实例。
例如,假设Person类有一个被许多类(包括非子类)使用的getName公共方法。但是有人只是将Employee作为Person的子类,并且Employee中的getName是受保护的,只能由子类访问,那么以前的代码将开始出现问题,而Employee将无法替换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
类中更少限制,我们需要将其访问修饰符删除(使其成为默认的)或将其设置为 protected
或 private
。
现在假设:
Human
中将 readAndGet
定义为 default
或 protected
,但 Human
在另一个包中定义Human
中将 readAndGet
定义为 private
readAndGet
方法的调用,但编译器不知道这一点,在两种情况下,代码都会成功编译,因为对于编译器来说,readAndGet
是从Mammal
类中调用的。readAndGet
,因为由于Human
类中readAndGet
的限制性访问,它将受到限制。//File Number 1
public class Human {
public int age = 21;
public int getAge() {
System.out.println("getAge() method in Human");
return age;
}
}
//File Number 2
public class Teacher extends Human {
public int getAge() {
System.out.println("getAge() method in Teacher");
return age;
}
}
//File Number 3
public class Characteristics {
public static void showAgeOfObject(Human human) {
human.getAge();
}
public static void main(String[] args) {
Human human = new Human();
Teacher teacher = new Teacher();
showAgeOfObject(human);
showAgeOfObject(teacher);
}
}
getAge() method in Human
getAge() method in Teacher