一:多态的基本介绍

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

二:多态的具体体现

1:方法的多态

重写和重载就体现多态

  1. package Data0801.Test0802;
  2. /**
  3. * 作者:sakura
  4. * 日期:2022年08月02日 00:05
  5. */
  6. public class test02 {
  7. public static void main(String[] args) {
  8. A a = new A();
  9. a.sum(3,4);
  10. a.sum(3,4,6);
  11. B b = new B();
  12. b.sum(2,4);
  13. }
  14. }
  15. class A{
  16. //重载
  17. public double sum(int a, int b){
  18. return a+b;
  19. }
  20. public double sum(int a, int b,int c){
  21. return a+b+c;
  22. }
  23. }
  24. class B extends A{
  25. @Override
  26. public double sum(int a, int b) {
  27. System.out.println("方法重写完毕");
  28. return super.sum(a, b);
  29. }
  30. }

2:对象的多态(重点,难点!!!)

:::danger

  1. 一个对象的编译类型和运行类型可以不一致
  2. 编译类型在定义对象是,就确定了,不能改变
  3. 运行类型是可以变化的
  4. 编译类型看定义是 = 好的左边,运行类型看 = 右边 :::

    1. Animal animal = new Dog(); //编译类型是Animal,运行类型是Dog
    2. animal = new cat(); //换了一个引用对象,运行类型变成了Cat

    三:代码案例

    1:多态基本体现

    1. public class test03 {
    2. public static void main(String[] args) {
    3. //编译类型和运行类型
    4. Animal animal = new Dog();
    5. animal.cry();
    6. Animal animal1 = new Cat();
    7. animal1.cry();
    8. }
    9. }
    10. public class Animal {
    11. public void cry(){
    12. System.out.println("动物在叫");
    13. }
    14. }
    15. public class Cat extends Animal{
    16. @Override
    17. public void cry() {
    18. System.out.println("猫在叫");
    19. }
    20. }
    21. public class Dog extends Animal{
    22. @Override
    23. public void cry() {
    24. System.out.println("狗在叫");
    25. }
    26. }

    2:解决主人给动物喂食的问题

    1. public class test04 {
    2. public static void main(String[] args) {
    3. Master sakura = new Master("sakura");
    4. Animal animal = new Cat("L");
    5. Food food = new fish("鱼");
    6. sakura.feed(animal,food);
    7. }
    8. }
    9. public class Master {
    10. private String name;
    11. public Master(String name) {
    12. this.name = name;
    13. }
    14. public void setName(String name) {
    15. this.name = name;
    16. }
    17. public String getName() {
    18. return name;
    19. }
    20. public void feed(Animal animal , Food food){
    21. System.out.println("主人:" + this.name + "给 " + animal.getName() + "喂食:" + food.getName());
    22. }
    23. }
    24. public class Food {
    25. private String name;
    26. public Food(String name) {
    27. this.name = name;
    28. }
    29. public String getName() {
    30. return name;
    31. }
    32. public void setName(String name) {
    33. this.name = name;
    34. }
    35. }
    36. public class fish extends Food{
    37. public fish(String name) {
    38. super(name);
    39. }
    40. }
    41. public class Animal {
    42. private String name;
    43. public Animal(String name) {
    44. this.name = name;
    45. }
    46. public String getName() {
    47. return name;
    48. }
    49. public void setName(String name) {
    50. this.name = name;
    51. }
    52. }
    53. public class Cat extends Animal{
    54. public Cat(String name) {
    55. super(name);
    56. }
    57. }

    四:多态细节注意事项和细节讨论

  • 多态的前提是:__两个对象(类)之间存在继承关系

    1:多态的向上转型

  • 本质:父类的引用指向子类的对象

  • 语法:父类类型 引用名 = new 子类类型( );
  • 特点:编译类型看左边,运行类型看右边
    • 可以调用父类的所有成员
    • 不能调用子类的特有成员
    • 最终运行效果看子类的具体实现 ```java Animal animal = new cat(); Objectobj = new cat(); //Object 也是cat的父类

//向上转型调用方法的规则如下: //(1)可以调用父类中的所有成员(需遵守访问权限) //(2)但是不能调用子类的特有的成员 //(3)因为在编译阶段,能调用哪些成员,是由编译类型来决定的 //animal.catchMouse();错误 // //(4)最终运行效果看子类(运行类型)的具体实现, 即调用方法时,按照从子类(运行类型)开始查找方法 //,然后调用,规则我前面我们讲的方法调用规则一致。

animal.eat(); //如果想调用子类中的特有方法只能,向下转型

  1. <a name="QlIMJ"></a>
  2. #### 2:多态的向下转型
  3. - **_语法:子类类型 __引用名 = (子类类型) 父类引用_**
  4. - **_只能强转父类的引用,不能强转父类的对象_**
  5. - **_要求父类的引用必须指向的时当前目标类型的对象_**
  6. - **_当向下转型后,可以调用子类类型中的所有的成员_**
  7. ```java
  8. Animal animal = new cat();
  9. Cat cat = (Cat)animal;

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

  1. public class PolyDetail02 {
  2. public static void main(String[] args) {
  3. //属性没有重写之说!属性的值看编译类型
  4. Base base = new Sub();//向上转型
  5. System.out.println(base.count);// ? 看编译类型 10
  6. Sub sub = new Sub();
  7. System.out.println(sub.count);//? 20
  8. }
  9. }
  10. class Base {
  11. //父类
  12. int count = 10;//属性
  13. }
  14. class Sub extends Base {
  15. //子类
  16. int count = 20;//属性
  17. }

五:instanceOF比较操作符

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

  1. public class PolyDetail03 {
  2. public static void main(String[] args) {
  3. BB bb = new BB();
  4. System.out.println(bb instanceof BB);// true
  5. System.out.println(bb instanceof AA);// true
  6. //aa 编译类型 AA, 运行类型是 BB //BB 是AA子类
  7. AA aa = new BB();
  8. System.out.println(aa instanceofAA); //true
  9. System.out.println(aa instanceofBB); //true
  10. Object obj = new Object();
  11. System.out.println(obj instanceofAA);//false
  12. String str = "hello";
  13. //System.out.println(str instanceof AA); //fase
  14. System.out.println(str instanceofObject);//true
  15. }
  16. }

六:Java动态绑定机制

  1. 当调用方法时,该方法会和该对象的内存地址/运行类型绑定
  2. 当调用对象的属性时,没有动态绑定机制,哪里调用哪里使用

image.png

  1. public static void main(String[] args) {
  2. A a = new B()
  3. System.out.println(a.sum()); //40
  4. System.out.println(a.sum(1); //30
  5. }
  6. class A {
  7. public int i= 10;
  8. public int sum() {
  9. return getl()+ 10;
  10. }
  11. public int sum1(){
  12. returni+ 10;
  13. }
  14. public int getl() {
  15. return i;
  16. }
  17. }
  18. class B extends A { // 子类
  19. public int i = 20;
  20. /*public int sum(){
  21. return i+ 20;
  22. }*/
  23. public int getl() {
  24. return i;
  25. }
  26. public int sum10 {
  27. returni+ 10;
  28. }
  29. }