java—为什么动态方法分派不能处理属性?

dvtswwa3  于 2021-09-13  发布在  Java
关注(0)|答案(2)|浏览(433)
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"; }
}

为什么动态方法分派不能处理属性?是否有任何目的,意义,或者它就是这样设计的。

dly7yett

dly7yett1#

有效地?因为与方法不同,字段不能被重写。从根本上说:这毫无意义。
重写方法时,不仅仅是名称。只有当一切都匹配时,它才算数。让我们试试这个:

public class Example {
    @Override public boolean equals(Example other) { return false; }
}

上面的内容不会编译,因为这与对象自身的equals不同。参数类型不匹配。作为一种语言语法,您可以“扩展”您的规范(您可以指定更具体的返回类型和更通用的参数类型,并且您可以选择声明更少的检查异常),但是如果您检查一个类文件,您将在自己的文件中找到父类的确切方法签名。
将这个概念扩展到字段,字段不仅仅是名称。它的名称和类型。
当你申报时 int x; 在里面 class Parent ,该字段存在于父类的所有示例中,包括父类的子类的任何示例。换句话说,你的 class Child extends Parent 类已具有一个x字段。你无法改变它的本质。这与方法形成了鲜明的对比,在方法中,您可以通过更改代码来重新定义它的功能。这不适用于字段:字段没有代码。
因此,当您声明一个与父级的方法声明具有相同签名的方法时,这是一个重写,但是:
当您声明一个与父类字段具有相同签名(相同名称、相同类型)的字段时,您是在声明另一个单独的字段,该字段的名称与父类字段的名称有阴影。
这种行为完全不同。简单的解决方案就是不声明 int x 一点也不,在孩子身上。写进父母的 x ,如果你必须的话。以上解释了为什么这种行为如此不同。

aiqt4smr

aiqt4smr2#

编写参与继承层次结构的类很困难。我们需要类来公开行为并允许子类进行定制,但不允许子类改变超类所依赖的东西。允许子类重写方法,但保持超类状态私有可以实现这种分离。
然而,如果子类可以覆盖超类中的变量,那么超类就不能信任它需要操作的变量,并且子类可以篡改超类。超类可以工作,也可以不工作,这取决于扩展它的内容。
如果这是一个特性,您可以选择是否使用它,类似于在c#中使用像virtual这样的关键字,但是对于方法,您什么时候会使用它?我想不出哪种情况有意义。

相关问题