【Java学习笔记】29 - (重要)多态 、动态绑定机制

项目代码

https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter08/src/com/yinhai/poly_

目录

项目代码

一、 多态的基本介绍

二、多态的快速入门

三、多态的细节和注意事项

1.多态存在的前提是两个对象存在继承关系

2.多态的向上转型(重要)

3.多态的向下转型 

4.属性没有重写一说,属性的值直接看编译类型

5.instanceOf比较操作符

 四、多态的练习

1.

2.

五、动态绑定机制(重要)

1.当调用对象方法的时候,该方法会和对象的内春地址/运行类型绑定

2.当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用

六、 多态的应用

1.多态数组

 2.多态参数


引出多态

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

public class Food {
    private String name;

    public String getName() {
        return name;
    }

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

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

}
class Fish extends Food{
    public Fish(String name) {
        super(name);
    }
}
class Bone extends Food{
    public Bone(String name) {
        super(name);
    }
}

public class Animal {
    private String name;

    public String getName() {
        return name;
    }

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

    public Animal(String name) {
        this.name = name;
    }
}
class Cat extends Animal{
    public Cat(String name) {
        super(name);
    }
}
class Dog extends Animal{
    public Dog(String name) {
        super(name);
    }
}

public class Master {
    private String name;

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

    public void feed(Dog dog,Bone bone){
        System.out.println("Master " + name + " feed " + dog.getName() + " " + bone.getName());
    }
    public void feed(Cat cat,Fish fish){
        System.out.println("Master " + name + " feed " + cat.getName() + " " + fish.getName());
    }
//.......当类变多时方法会变得很多
}
public class Poly01 {
    public static void main(String[] args) {
        Master master = new Master("Jack");
        Dog dog = new Dog("xiaoYellow");
        Bone bone = new Bone("gutou");
        master.feed(dog,bone);
        System.out.println(" ================== ");
        Cat cat = new Cat("xiaoWeith");
        Fish fish = new Fish("zayu");
        master.feed(cat,fish);
    }
}

引出一个问题,当后续对象变多的时候,feed方法会变得冗余,多次重载, 很麻烦,而且不利于代码维护

一、 多态的基本介绍

方法或者对象具有多种形态,是面向对象的第三大特征,多态是建立在封装和继承的基础之上的

1.方法的多态 重写和重载都能体现多态

package com.yinhai.poly_;

public class PloyMethod {
    public static void main(String[] args) {
        A a = new A();
        a.sum(10,20);
        a.sum(10,20,30);//The method overloading represents polymorphism

        B b = new B();
        a.say();
        b.say(); //The method overriding represents polymorphism
    }
}
class B{
    public void say(){
        System.out.println("This the Class B is used of method");
    }
}
class A extends B {
    public int sum(int n1,int n2){
        return n1 + n2;
    }
    public int sum(int n1,int n2,int n3){
        return n1 + n2 + n3;
    }
    public void say (){
        System.out.println("This the Class A is used of method");
    }
}

2.对象的多态(重要)

1)一个对象的变异类型和运行类型可以不一致

         Animal animal = new Dog(); animal的变异类型是animal,运行类型是Dog

2)变异类型在定义对象时,就确定了,不能改变

3)运行类型是可以改变的

    anmial = new Cat();

4)编译类型看定义时 = 号的左边,运行类型看 = 的右边

案例

package com.yinhai.poly_.polyobject;

public class PolyObject {
    public static void main(String[] args) {
        //The characteristics of object polymorphism
        Animal animal = new Dog(); //The compile type is determined of Animal class
        //But opera type is Dog of class
        animal.cry();//because when run this line,system will find opera type of object,and its Dog of class
        //so cry's method is Dog of class,system output "Dog crying...."
        animal = new Cat(); //attention,right here that compil type still of Animal,but run type is change to Cat class
        animal.cry();//now,system should be output "Cat crying..."
    }
}

                

二、多态的快速入门

package com.yinhai.poly_.poly01;
public class Poly01 {

    public static void main(String[] args) {
        Master master = new Master("Jack");
        Dog dog = new Dog("xiaoYellow");
        Bone bone = new Bone("gutou");
        master.feed(dog, bone);//run type is dog ,that can passing in Base class of Animal
        //in other words,this is one way to used polymorphism,compil type not equal to run type

        System.out.println(" ================== ");
        Cat cat = new Cat("xiaoWeith");
        Fish fish = new Fish("zayu");
        master.feed(cat, fish);
    }

}

public class Master {
    private String name;

    public Master(String name) {
        this.name = name;
    }
    //now,can use polymorphism to solve that problem
    public void feed(Animal animal,Food food){//compil type is Animal can point to object of Animal's subclasses
        //compil type is Food can point to object of Food's subclasses
        //can passing in all object of subclasses of compil type
        System.out.println("Master " + name + " feed " + animal.getName() + " " + food.getName());
    }
    public void feed(Cat cat, Fish fish){
        System.out.println("Master " + name + " feed " + cat.getName() + " " + fish.getName());
    }
}

三、多态的细节和注意事项

1.多态存在的前提是两个对象存在继承关系

2.多态的向上转型(重要)

        1)本质,父类的引用指向了子类的对象(有点像把子类提到父类)

public class PolyDetail {
    public static void main(String[] args) {
        //transition up; the reference to base class point to the object of subclasses
        Animal cat = new Cat();
        //Object obj = new Cat(); //can run? the answer is yes
    }
}

        2)语法:父类类型 引用名 = new 子类类型();

        3)特点:变异类型看左边,运行类型看右边

                可以调用父类中的所有成员(方法)(需遵守访问权限)

                不能调用子类中的特有成员(方法);

因为在编译阶段能调用的成员是由编译类型来决定的

编译类型的父类里都没这个方法,当然会报错,但运行时就是看运行类型的子类里找

                最终运行效果看子类的具体实现 

即调用方法时,按照从子类开始查找方法

package com.yinhai.poly_.polydetail;

public class Animal {
    String name = "animal";
    int age = 10;
    public void sleep(){
        System.out.println("sleeping...");
    }
    public void run(){
        System.out.println("running...");
    }
    public void eat(){
        System.out.println("eating...");
    }
    public void show(){
        System.out.println("Hello~");
    }
}
public class Cat extends Animal{
    public void eat(){//constitute override of method
        System.out.println("Cat eating fish...");
    }
    public void catCatch(){
        System.out.println("Catching mouse...");
    }

}

public class PolyDetail {
    public static void main(String[] args) {
        //transition up; the reference to base class point to the object of subclasses
        Animal cat = new Cat();
        //Object obj = new Cat(); //can run? the answer is yes
        //Object also base type of Cat
        //cat.catCatch; this line was wrong
        cat.eat();//eat method existence in cat class,so output "Cat eating..."
        cat.run();//in cat class,system cant find method,
//so jump to Anmial class to find out eat method
        cat.sleep();//Same as above
        cat.show();//Same as above
    }
}

3.多态的向下转型 

1)语法:子类类型 引用名 = (子类类型)父类引用;

        //transition down of polymorphism
        //compilation type is Cat , run type also is Cat
        Cat cat = (Cat) animal;
        //Dog dog = (Dog) animal; // attention , a reference of base class must point to same object of subclasses
        cat.catCatch();//so this line can passing in Cat class to output "Cat catch mouse"

2)只能强转父类的引用,不能强转父类的对象

3)要求父类的引用必须指向的是当前目标类型的对象

                

4)当向下转型后,就可以调用子类类型中的所有成员

4.属性没有重写一说,属性的值直接看编译类型

public class PolyDetail02 {
    public static void main(String[] args) {
        Base base = new Sub();
        System.out.println();
        System.out.println(base.count);//10
        Sub sub = new Sub();
        System.out.println(sub.count);//20
    }
}
class Base{
    int count = 10;
}
class Sub extends Base{
    int count = 20;
}

5.instanceOf比较操作符

        用于判断对象的运行类型是否为XX类型或XX类型的子类型

public class polyDetail03 {
    public static void main(String[] args) {
        BB bb = new BB();
        System.out.println(bb instanceof BB);//true
        System.out.println(bb instanceof AA);//true
        AA aa = new AA();//compilation type is AA,run type is BB
        System.out.println(aa instanceof AA);//true
        System.out.println(aa instanceof BB);//false so this is run type judgement
        Object o = new Object();
        System.out.println(o instanceof AA);//false
        
    }
}
class AA{

}
class BB extends AA{

}

 四、多态的练习

1.

boolean b = (boolean)in错误 不是一个类型

Srtring str = (String)objPri错误 不是一个类型 指向Interger 的父类引用无法转成String 

2.

        

五、动态绑定机制(重要)

        

package com.yinhai.poly_.dynamic_;

public class DynamicBinding {
    public static void main(String[] args) {
        A a = new B();
        System.out.println(a.sum());//40 -->30
        System.out.println(a.sum1());//30 --> 20
    }
}
class A {
    public int i = 10;
    public int sum(){//run this statement
        return getI() + 10;//and run getI , so here is a question ,where is run to? is A or B?
        //so elicitation dynamic binding

        //mechanism of dynamic binding
        //1.when running object method,this object method will bind to run type
        //so getI will use method of class B
        //output 30
        //2.when running parameter of object,have not dynamic binding! in other way , where declaration where used
    }
    public int sum1(){
        return i + 10;//so run this line,here is will return i,this parameter is class A,have not dynamic binding!
    }
    public int getI(){
        return i;
    }
}
class B extends A{
    public int i = 20;
    // public int sum(){
    //     return getI() + 10; //to find class A of sum method ,if be annotated with this statement
    // }
    // public int sum1(){
    //     return i + 10; //to find sum method of class A ,if be annotated with this statement
    // }
    public int getI(){
        return i; //not dynamic binding
    }
}

1.当调用对象方法的时候,该方法会和对象的内春地址/运行类型绑定

2.当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用

六、 多态的应用

1.多态数组

package com.yinhai.poly_.polyarr_;

public class PloyArray {
    public static void main(String[] args) {
        Person[] persons = new Person[5];//dynamic array
        persons[0] = new Person("JACK",20);
        persons[1] = new Student("xiaoming",18,60);
        persons[2] = new Student("xiaohuang",20,99);
        persons[3] = new Teacher("Mr.huang",26,9000);
        persons[4] = new Teacher("Ms.wang",26,7000);
        //iterate over array to running 'say' method
        for(int i = 0;i < persons.length;i++){
            //compilation type of person[i] is fixed,but run type is dynamic
            System.out.println(persons[i].say());
            if(persons[i] instanceof Student){//to use for unique method of subclass
                //use the instanceof statement to determine if this is the same type or subclasses
                Student student = (Student) persons[i];
                student.study();//transition down to use method of subclasses
                //((Student) persons[i]).study();
                // can also use this statement ,that also can output the study method
            } else if(persons[i] instanceof Teacher){
                //same above if statement
                Teacher teacher = (Teacher) persons[i];
                teacher.teach();//same above
                //((Teacher) persons[i]).teach();//same above
            }else if (persons[i] instanceof Person){

            }
            else{
                System.out.println("Have one data is neither student " +
                        "nor teacher,please check correctness of the data ");
            }
        }

    }
}
public class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    public String say(){
        return name + " " + age;
    }
}
public class Student extends Person{
    private double score;
    public Student(String name, int age,int score) {
        super(name, age);
        this.score = score;
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }

    public String say() {
        return super.say() + " score=" + score;
    }
    public void study(){
        System.out.println(super.getName() + " studying...");
    }
}
public class Teacher extends Person{
    private double salary;

    public Teacher(String name, int age, double salary) {
        super(name, age);
        this.salary = salary;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    @Override
    public String say() {
        return super.say() + " salary=" + salary;
    }
    public void teach(){
        System.out.println(super.getName() + " teaching...");
    }
}

        

 2.多态参数

public class PolyParameter {
    public static void main(String[] args) {
        Employee boss = new Manger("boss",20000,120000);
        Employee xiaowang = new OrdinaryStaff("xiaowang", 2000);
        A a = new A();
        a.showEmpAnnal(boss);
        a.showEmpAnnal(xiaowang);
        a.testWork(boss);
        a.testWork(xiaowang);
    }
}
class A{
    public void showEmpAnnal(Employee e){
        System.out.println(e.getName() + " " +  e.getAnnual()) ;
    }
    public void testWork(Employee e){
        if(e instanceof Manger){
            ((Manger) e).manage();
        }else if (e instanceof OrdinaryStaff){
            ((OrdinaryStaff) e).work();
        }
    }
}
public class Employee {
    private String name;
    private int salary;
    public int getAnnual(){
        return salary * 12;
    }

    public Employee(String name, int salary) {
        this.name = name;
        this.salary = salary;
    }

    public String getName() {
        return name;
    }

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

    public int getSalary() {
        return salary;
    }

    public void setSalary(int salary) {
        this.salary = salary;
    }
}
public class Manger extends Employee{
    private int bones;
    public int getAnnual(){
        return super.getAnnual();
    }

    public Manger(String name, int salary,int bones) {
        super(name, salary);
        this.bones = bones;
    }
    public void manage(){
        System.out.println(getName() + " managing...");
    }

    public int getBones() {
        return bones;
    }

    public void setBones(int bones) {
        this.bones = bones;
    }
}
public class OrdinaryStaff extends Employee{

    public void work(){
        System.out.println(getName() + " working...");
    }
    public int getAnnual(){
        return  super.getAnnual();
    }

    public OrdinaryStaff(String name, int salary) {
        super(name, salary);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yinhai1114

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值