Java 多态(polymorphism)

564 查看

父类对象被定义成子类类型(家族的具体化)

既然子类继承父类,所以子类更能代表这一个家族的具体表现,一个父类的对象被定义成子类类型时就具有了父类的属性和方法。

反过来子类对象不能被定义成父类类型

子类对象为什么不能被定义成父类类型呢?因为子类继承于父类,因此子类拥有的方法很可能比父类多,因为除了继承自父类的全部属性和方法外,子类有可能定义了其他的方法,所以大体上看子类的量级要比父类大,所以父类对象可以定义成子类对象,因为多出来的方法可以直接使用子类的,而反过来的话就不行了,因为子类对象不知道如何砍掉那些多出来的方法。

所以,一句话就是小盒子(父类对象)可以套进大盒子(子类)里,大盒子(子类对象)不能套进小盒子(父类)里。

同理,父类对象可以被子类对象赋值(被定义成子类类型),子类对象不能被父类对象赋值。

父类对象只有当明确转换为子类对象时才可以直接控制对象中的属性,只是通过赋值来使父类对象变成子类类型的办法不能使父类对象完全控制对象中的属性。

public class ParentChildTest {
    public static void main(String[] args)
     {
        Parent parent=new Parent();
        parent.printValue();
        Child child=new Child();
        child.printValue();

        System.out.println(parent.getClass().getName());
        parent=child;
        ((Parent)parent).printValue();
        System.out.println(parent.getClass().getName());

        parent.myValue++;
        ((Parent)parent).printValue();

        ((Child)parent).myValue++;
        parent.printValue();

    }
}

class Parent{
    public int myValue=100;
    public void printValue() {
        System.out.println("Parent.printValue(),myValue="+myValue);
    }
}
class Child extends Parent{
    public int myValue=200;
    public void printValue() {
        System.out.println("Child.printValue(),myValue="+myValue);
        super.printValue();
    }
}

如果子类与父类有相同的字段,则子类中的字段会代替或隐藏父类的字段,子类方法中访问的是子类中的字段(而不是父类中的字段)。
换言之,一旦子类父类具有相同名称的字段,就会使继承的情况变得复杂,子类中的父类同名变量或方法就会褪色而不易被调用。

比如,父类子类都有名为F的属性或方法,那么在继承时,子类就会有两个F属性或方法,一个继承于父类(由父类定义),而另一个由子类自己定义。生成一个子类对象时,子类对象一旦调用F属性或执行F方法就会优先使用子类自己的F属性或执行子类自己的F方法,如果要强行使用父类的F属性或执行父类F方法,得在子类定义中使用super.F()来调用。

多态的本质是父类对象引用子类对象。
利用抽象类和接口,不直接定义那些抽象的父类方法,子类方法分别个性化地重写各自的方法。
当要构建一批继承于同一父类的对象时,只需要使得父类对象引用子类对象,就可以使得构造出的这批子类对象的类型一致(父类类型),这样做可以大大简化后续操作,因为子类化的父类对象调用的都是子类的属性和方法。所以,导致这些对象调用的属性和方法依据它的真实类型(引用的子类型)而定,即变成不同的属性和方法,固称多态。

public class FeedTest 
{
    public static void main(String[] Args)
    {
        Administrator adm = new Administrator();
        Animal[] animalFactory = new Animal[100];
        for(int i = 0;i<10;i++)
        {
            animalFactory[i]=new Monkey();
            System.out.println("动物工厂正在生产"+animalFactory[i].variety);
            animalFactory[i].eat();
        }
        for(int i = 10;i<20;i++)
        {
            animalFactory[i]=new Lion();
            System.out.println("动物工厂正在生产"+animalFactory[i].variety);
            animalFactory[i].eat();
        }
        for(int i = 20;i<30;i++)
        {
            animalFactory[i]=new Pigeon();
            System.out.println("动物工厂正在生产"+animalFactory[i].variety);
            animalFactory[i].eat();
        }
        adm.feedAnimal(animalFactory);
    }
}

abstract class Animal
{
    public String variety;
    public abstract void eat();
}

class Monkey extends Animal
{
    Monkey() 
    {
        this.variety = "猴子";
    }
    public void eat()
    {

        System.out.println("猴子吃桃子");
    }
}

class Lion extends Animal
{
    Lion()
    {
        this.variety = "狮子";
    }
    public void eat()
    {
        this.variety = "狮子";
        System.out.println("狮子吃肉");
    }
}

class Pigeon extends Animal
{
    public Pigeon() 
    {
        this.variety = "鸽子";
    }
    public void eat()
    {
        System.out.println("鸽子吃玉米粒");
    }
}

class Administrator
{
    public String name = "小王";
    public void feedAnimal(Animal[] af)
    {
        System.out.println("Feeding");
    }

}