多态是否适用于Java中的类属性?

Ton*_*Joe 12 java polymorphism

我知道当使用父类引用来引用子类对象时,OOP中多态性的常见用法是这样的:

Animal animal = new Animal();
Animal dog = new Dog();
Run Code Online (Sandbox Code Playgroud)

我知道多态性适用于类方法,但它是否也适用于类属性?我尝试用这个小例子来测试它:

public class Main{

    public static void main(String args[]){
        Animal animal = new Animal();
        Animal dog1 = new Dog();
        Dog dog2 = new Dog();

        System.out.println("Animal object name: " + animal.name);
        System.out.println("Dog1 object name: "+dog1.name);
        System.out.println("Dog2 object name: " + dog2.name);

        animal.print();
        dog1.print();
        dog2.print();
    }

}
class Animal{
    String name = "Animal";
    public void print(){
        System.out.println("I am an: "+name);
    }
}
class Dog extends Animal{
    String name = "Dog";
    public void print(){
        System.out.println("I am a: "+name);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是输出:

Animal object name: Animal
Dog1 object name: Animal
Dog2 object name: Dog
I am an: Animal
I am a: Dog
I am a: Dog
Run Code Online (Sandbox Code Playgroud)

正如您所看到的(我希望它很清楚),多态性与print()方法一起正常工作,但是对于class属性"name",它取决于引用变量.

所以,我是对的吗?多态性不适用于类属性?

小智 8

扩展类时,方法会被覆盖,但字段会被隐藏.动态分派适用于方法,但不适用于字段.为什么语言设计如此,天知道为什么.


Zar*_*wan 6

不,它没有.实例变量是特定类的属性,不会直接受到超类或子类和多态的影响.

您仍然可以通过在Dog中使用"super.name"和"this.name"来访问这两个字段,但如果您只使用"名称",那么Dog中的那个将接管.如果你想要另一个你明确需要调用super.请注意,我在谈论访问Dog类中的变量.


And*_*eas 5

Dog.name隐藏 Animal.name,这是一个非常糟糕的方式做到这一点。任何好的 IDE 都会警告您正在这样做。

两个实例字段都存在,您可以从Dogasthis.name和访问super.name

  • @nikpon 那太*错误*了。仅仅因为你可以做某事,并不意味着你就可以做它。获取任何源文件,将所有字段和变量名称更改为 30 个字符的随机名称,然后从源文件中删除所有注释和换行符,因此整个文件是一行。*那*完全有效,可以毫无问题地编译和运行,但仍然*非常错误*。 (3认同)

Tor*_*rge 5

Animal 字段被 Dog 字段隐藏,您仍然可以通过引用它来访问 Animal 字段。

您期望的行为可以通过这种方式实现:

public class Main{

    public static void main(String args[]){
        Animal animal = new Animal();
        Animal dog1 = new Dog();
        Dog dog2 = new Dog();

        System.out.println("Animal object name: " + animal.name);
        System.out.println("Dog1 object name: "+dog1.name);
        System.out.println("Dog2 object name: " + dog2.name);

        animal.print();
        dog1.print();
        dog2.print();
    }

}
class Animal {
    String name = "Animal";

    public void print(){
        System.out.println("I am an: "+name);
    }
}
class Dog extends Animal{
    public Dog() {
       this.name = "Dog"
    }
}
Run Code Online (Sandbox Code Playgroud)