Java中的多态,为什么要用多态?多态的注意事项和细节

问题:编写一个程序,Master类中有一个feed(喂食)方法,可以完成主人给动物喂食的信息

原本方法:在master类中对feed方法用类的重载

代码:

//测试类
public class Test {
    public static void main(String[] args) {
        String name = "ret";
        Dog dog = new Dog("小黄狗");
        Bone bone = new Bone("大骨头");
        Master master = new Master("ret");
        master.feed(dog,bone);

        Cat cat = new Cat("小花猫");
        Fish fish = new Fish("小鱼");
        master.feed(cat,fish);
    }
}

//Master类
public class Master {
    String name;

    public Master(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void feed(Dog dog,Bone bone){
        System.out.println(name+"给"+dog.getName()+"喂"+bone.getName());
    }

    public void feed(Cat cat,Fish fish){//没使用对象的多态,用的是方法的重载,代码冗余,且不易扩展和维护
        System.out.println(name+"给"+cat.getName()+"喂"+fish.getName());
    }
}

//Animal类
public class Animal {
    private String name;

    public Animal(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

//Dog类,继承Animal类
public class Dog extends Animal{
    public Dog(String name) {
        super(name);
    }
}

//Cat类,继承Animal类
public class Cat extends Animal{
    public Cat(String name) {
        super(name);
    }
}

//Food类
public class Food {
    private String name;

    public Food(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

//Bone类,继承Food类
public class Bone extends Food{
    public Bone(String name) {
        super(name);
    }
}

//fish类,继承Food类
public class Fish extends Food{
    public Fish(String name) {
        super(name);
    }
}

使用对象的多态解决上述代码问题,只需要修改Master类中的feed方法即可

代码:

public void feed(Animal animal,Food food){//对象的多态,向上转型
        System.out.println(name+"给"+animal.getName()+"喂"+food.getName());
    }

上述对象的多态,是父类的引用指向了子类的对象,属于向上转型

Animal animal = new Dog();  Animal animal = new Cat();  

Food food = new Bone(); Food food = new Fish();

注:

  1. 编译类型在定义对象时,就已经确定了,不能改变。
  2. 运行类型是可以变化的。
  3. 编译时看=的左边,运行时看=右边。如:Animal animal = new Dog(); animal的编译类型时Animal,运行类型是Dog。
  4. 向上转型的对象的引用只能调用父类中的成员(属性和方法),需要遵循访问权限,不能调用子类中特有的成员,如:在Dog类中添加cry方法,则animal.cry();是错的。但是可以通过向下转型来解决这个问题。
  5. 最终运行效果看子类(运行类型)的实现,即调用方法时,按照从子类(运行类型)开始查找方法,然后调用,子类没有看父类...
在Dog类中添加cry方法
public void cry(){
    System.out.println("汪汪汪!!!");
}

在feed方法中用animal.cry();是错的。可以通过向下转型来解决这个问题。如:

if (animal instanceof Dog) {//instanceof比较操作符,用于判断对象的运行类型是否为××类型或××类型的梓类型,这里为了避免ClassCastException错误,因为不能将cat转为Dog类型
    Dog dog = (Dog) animal;//animal是指向Gog类型的对象才能向下转型
    dog.cry();
}

属性没有重写之说,属性的值看编译类型

代码:

public class Test5 {
    public static void main(String[] args) {
        Base base = new Base();
        System.out.println(base.count);//这边只是用于测试,一般来说属性是private,不能直接访问,而是同get方法
        Sub sub = new Sub();
        System.out.println(sub.count);
    }
}

class Base{
    int count = 10;
}

class Sub extends Base{
    int count = 20;
}

输出结果为:

10

20

 

你可能感兴趣的:(java,开发语言)