多态性在行动

Polymorphism in action

我在 Java 中遇到了一些我无法理解的代码。它在 java.

中使用了多态性
public class MyAnimalList {
    private Animal[] animals = new Animal[5];
    private int nextIndex = 0;

    public void add(Animal a) {
        if (nextIndex < animals.length) {
            animals[nextIndex] = a;
            System.out.println("Animal added at " + nextIndex);
            nextIndex++;
        }
    }
}


public class AnimalTestDrive{
    public static void main (String[] args) {
        MyAnimalList list = new MyAnimalList();
        Dog a = new Dog();
        Cat c = new Cat();
        list.add(a);
        list.add(c);
    }
}

这里引用变量a,它引用堆上的狗对象,被传递给add函数。现在,当引用作为参数并作为参数接收时 Animal a。我的问题从这里开始,animals[0]=a,即animals[0]指的是a所引用的对象。 animals[1]=a也就是说它也指向了a所引用的对象,也就是同一个对象。

那么如果所有的动物数组引用都指向同一个对象,那么新的 dog-list 是如何创建的呢?

有两个不相关的东西名为 a。一个 class 的 main 方法中有一个局部变量,另一个 class 的 add 方法有一个参数。在方法中声明的局部变量在该方法之外是不可见的,因此 add 方法看不到在 main 方法中声明的 a

main 中调用 add 方法的代码为每次调用提供不同的对象,因此引用不指向同一个对象; add 方法的参数指向传入的任何内容。在第一次调用 add 时,参数 a 引用了 main 方法中局部变量 a 引用的 Dog。第二次调用add时,参数a引用了局部变量c.

引用的Cat
Dog a = new Dog();

这里,a是对Dog对象的引用。

此引用已传递给 add(Object a) 方法。

这里,a是一个Dog引用变量,被转换成一个Animal引用变量。但仍然指向同一个 Dog 对象。尽管它现在是一个 Animal 引用变量。然后将其传递并添加到列表中。

不要混淆 Dog aadd(Animal a).. 这两个 a 引用是完全不同的。 Dog a,在传递给方法时被转换为 Animal a。这两个不是一回事。您可以随心所欲地命名它们。

这一切都是可能的,因为 class Dog extends Animal

现在,假设有 3 个 Dog 对象

Dog a = new Dog();
Dog b = new Dog();
Dog c = new Dog();

并且假设在Dogclass中有一个实例变量String name;

因此,对于每个 Dog 对象,您可以设置不同的名称。

a.setName("Tom");
b.setName("Dick");
c.setName("Harry");

现在您可以通过以下方式将这些添加到列表中,

list.add(a);
list.add(b);
list.add(c);

所有对象引用都转换为 Animal 引用并添加到同一个列表中。但它们都指代不同的对象。在数组中具有不同的名称。

现在,类似地,Cat class 也扩展了 Animal。因此,您可以创建 Cat 个对象并将它们转换为 Animal 个对象,然后将它们也添加到列表中。

因此,不是只有 Dog 个对象的数组 Dog[]Cat 个对象的数组 Cat[],我们只能将 Dog 个对象,或 Cat 个对象,我们可以利用 多态性 ,并创建一个超类数组 Animal 并转换子类 class个对象全部放入Animal个superclass个对象中,然后全部放在数组中。 CatDog 对象一起留在列表中。

您可能会对在您的主代码中有 Dog 变量 'a' 并且在您的 'add' 方法中也有一个具有相同名称的变量感到困惑。

但我希望我能以最好的方式回答你的问题。

当你说

list.add(a);

实际发生的事情是,当您调用该方法时,您会得到一个引用旧对象的新对象(这意味着您在方法中对该对象所做的所有更改都将保留在原始对象中)并且您可以把它想象成——暂时地——改变你的原始变量的名称。

这意味着当你说

list.add(c); what you have in your add method is a Animal type Cat in the variable a.