public class Main {
public static void main(String[] args) {
Parent p = new Child();
System.out.println(p.x); // 10 is printed
System.out.println(p.print()); // Child is printed
}
}
class Parent{
int x = 10;
public String print(){ return "Parent";}
}
class Child extends Parent{
int x = 55;
public String print(){ return "Child"; }
}
为什么动态方法分派不能处理属性?是否有任何目的,意义,或者它就是这样设计的。
2条答案
按热度按时间dly7yett1#
有效地?因为与方法不同,字段不能被重写。从根本上说:这毫无意义。
重写方法时,不仅仅是名称。只有当一切都匹配时,它才算数。让我们试试这个:
上面的内容不会编译,因为这与对象自身的equals不同。参数类型不匹配。作为一种语言语法,您可以“扩展”您的规范(您可以指定更具体的返回类型和更通用的参数类型,并且您可以选择声明更少的检查异常),但是如果您检查一个类文件,您将在自己的文件中找到父类的确切方法签名。
将这个概念扩展到字段,字段不仅仅是名称。它的名称和类型。
当你申报时
int x;
在里面class Parent
,该字段存在于父类的所有示例中,包括父类的子类的任何示例。换句话说,你的class Child extends Parent
类已具有一个x字段。你无法改变它的本质。这与方法形成了鲜明的对比,在方法中,您可以通过更改代码来重新定义它的功能。这不适用于字段:字段没有代码。因此,当您声明一个与父级的方法声明具有相同签名的方法时,这是一个重写,但是:
当您声明一个与父类字段具有相同签名(相同名称、相同类型)的字段时,您是在声明另一个单独的字段,该字段的名称与父类字段的名称有阴影。
这种行为完全不同。简单的解决方案就是不声明
int x
一点也不,在孩子身上。写进父母的x
,如果你必须的话。以上解释了为什么这种行为如此不同。aiqt4smr2#
编写参与继承层次结构的类很困难。我们需要类来公开行为并允许子类进行定制,但不允许子类改变超类所依赖的东西。允许子类重写方法,但保持超类状态私有可以实现这种分离。
然而,如果子类可以覆盖超类中的变量,那么超类就不能信任它需要操作的变量,并且子类可以篡改超类。超类可以工作,也可以不工作,这取决于扩展它的内容。
如果这是一个特性,您可以选择是否使用它,类似于在c#中使用像virtual这样的关键字,但是对于方法,您什么时候会使用它?我想不出哪种情况有意义。