java的多态

java的多态

引入的原因

public class Test {
    public static void main(String[] args) {
        Master master = new Master("tim");
        Dg dog = new Dog("金毛");
        Cat cat = new Cat("蓝猫");
        Fish fish = new Fish("小鱼干");
        Bone bone = new Bone("鸡锁骨");
        master.feed(dog,bone);
        master.feed(cat,fish);
        }
  }
 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());
    }

随着多个动物,食物的增加,对于代码整体而言,代码复用性不高,不利于代码维护,所以引入多态

多态(羊皮狼)

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

(1)方法的多态

​ 重载和重写就体现多态

(2)对象的多态(核心)

  1. 一个对象的编译类型和运行类型可以不一致

Animal animal = new Dog();
2. 编译类型在定义对象时,就确定了不能改变
3. 运行类型是可以变化的
4. 编译类型看定义时 等号的最左边, 运行类型看 等号的最右边

Animal animal = new Dog();
animal 只是对象引用, new Dog() 才是对象

对象的多态: 可以让一个父类的引用 指向 一个子类的对象

animal 的编译类型是Animal,运动类型是Dog

animal= new Cat(); animal 的编译类型是Animal,运动类型变成了Cat

练习

package com.hspedu.Poly_.objectpoly_;

public class Dog extends Animal{

    public void cry() {
        System.out.println("狗:你在狗叫什么...");
    }
}
package com.hspedu.Poly_.objectpoly_;

public class Cat extends Animal{

    public void cry() {
        System.out.println("猫:你在猫叫什么");
    }
}
package com.hspedu.Poly_.objectpoly_;

public class Animal {
    public static void main(String[] args) {
        Animal animal_1 = new Animal();//编译类型是Animal,运行类型是Animal
        Animal animal_2 = new Dog();//编译类型是Animal,运行类型是Dog
        animal_2.cry();//此时的编译类型是Animal,运行类型是Dog
        animal_2 = new Cat();//此时的编译类型仍然是Animal,但运行类型变成了Cat
        animal_2.cry();//此时的编译类型是Animal,运行类型是Cat

    }
    public  void  cry() {
        System.out.println("Animal动物在叫....");
    }
}

2.

//animal 编译类型是 Animal,可以指向Animal子类的对象
    //food 编译类型是 Food,可以指向Food子类的对象
    
public void feed(Animal animal,Food food) {  System.out.println(this.name+"给"+animal.getName()+"喂"+food.getName());
    }
public class Test {
    public static void main(String[] args) {
        Master master = new Master("Jack");
        Dog dog  = new Dog("金毛");
        Cat cat  = new Cat("蓝猫");
        Fish fish = new Fish("小鱼干");
        Bone bone = new Bone("鸡锁骨");

        master.feed(dog ,bone);
        master.feed(cat,fish);
    }
}

多态的向上转型

  1. 本质:父类的引用指向了子类的对象

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

  3. 特点:编译类型看左边,运行类型看右边

    可以调用父类中的所有成员(需要看访问权限),不能调用子类中特有成员

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

    package com.hspedu.hhh;
    
    public class ss {
        public  void sss() {
            System.out.println("sss");
        }
    }
    
    package com.hspedu.hhh;
    
    public class Animal extends  ss {
        String name = "动物";
        int age = 10;
        public void sleep() {
            System.out.println("睡");
        }
        public  void run() {
            System.out.println("跑");
        }
        public void eat() {
            System.out.println("吃");
        }
        public void show() {
            System.out.println("hello");
        }
    }
    
    
    package com.hspedu.hhh;
    
    public class cat  extends Animal{
        public void eat() {    //方法重写
            System.out.println("猫吃鱼");
        }
        public  void  catMouse() {
            System.out.println("猫抓老鼠");
        }
    
    }
    
    
    package com.hspedu.hhh;
    
    public class Test {
        public static void main(String[] args) {
            Animal animal = new cat();
           //animal.catMouse() 不能调用,编译后animal只能调用自己成员
            // 因为在编译阶段,能调用哪些成员,是由编译类型来决定的
            animal.eat();//猫吃鱼
            //编译类型是父类,执行父类的成员,但运行时按照特指的子类执行重写父类的方法,所以子类重写是关键,
            // 而且执行过程中遵循就近原则,先找特指运行的子类,再依次往上找,直到找到为止
            animal.sleep();
            animal.run();
            animal.show();
            //特指的运行子类找不到该方法,就会向编译环境父类Animal找仍未果,再从上级父类直到找到为止
            animal.sss(); //sss
        }
    }
    
    

    向下转型

    为了让父类指向子类,并且父类引用也可以访问子类的所有成员(除特殊权限)

    1. 语法 子类类型 引用名 = (子类类型) 父类引用`;
    2. 只能强转父类的引用,不能强转父类的对象
    3. 要求父类的引用必须指向是当前目标类型的对象
    4. 可以调用子类类型中的所有成员
    package com.hspedu.hhh;
    
    public class Test {
        public static void main(String[] args) {
            Animal animal = new cat();
           //animal.catMouse() 不能调用,编译后animal只能调用自己成员
            //如果想调用只能使用向下转型
            // 向上转型,访问范围看父类的成员,执行看子类;而向下转型,访问范围看子类的成员,执行看子类
    
            cat c_at = (cat) animal;//和new的区别是,没有创建新的对象
            c_at.catMouse();//猫抓老鼠
            c_at.eat();//猫吃鱼
    
        }
    }
    

    注意

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

    2. instanceOf比较操作符,用于判断对象的运行类型是否为xx类型或者xx类型的子类型

    3. 动态绑定机制

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值