2021-1-22

C++的多态有两种体现形式
动态的多态就和Java差不多,需要使用virtual这个关键字,被这个关键字修饰的方法才能被子类重写.
2.Java中集合类.各种数据结构的内置实现.顺序表,链表,哈希表,二叉树…
使用集合类的时候,经常也会涉及到多态.
3.

class A {
    public A(){
/ / this的类型是A类型,实际对应的是整个子类的实例
//而A的父类就是0bject 了, Object没有 func方法
   this.func();
   }
   public void func(){
        System.out. println("A.func");
  }
}
class B extends A {
     private int num = 1;
     @Override
     public void func() {
                super.func();
                System.out.println("B. func" + num);
     }
}
//通过这个代码来说明,在构造方法中调用重写的方法带来的问题.
public class Test2 {
        public static void main(String[] args) {
// 1.A是B的父类,构造B的时候,就需要先构造A的实例
// 2.构造A的实例,就会调用A的构造方法
// 3.调用A的构造方法的时候,此时就会调用到 this. func().此时的this是指向子类的实例,触发
//4.如果在 B.func打印 B的num属性的值,就会发现,结果是0,在执行父类的构造方法的时候就前//而此时此刻,B的初始化代码(包括就地初始化和代码块以及构造方法都没有执行到呢)
//这个代码是比较容易让人误会的,实际开发中不建议这么写,
//不建议在构造方法中调甩草纯的专法,尤其是可能被重写的方法.
//在实现构造方法的时候不卿只允行简单的赋值操作,让实例能够尽快进入到工作状态.
B b= new B();
}

4.//如果光看这一句 add 的代码,是不需要知道当前的 list 究竟是顺序表还是链表的

 list. add("he11o");

从程序猿的角度:
多态的目的是为了让程序猿写代码更简单.
光看这一行代码,就不需要考虑实际的类型.
从JVM运行的角度:
JVM需要结合上下文,理清楚list 实际指向的对象,决定add 执行哪个版本的方法.
多态
一、向上转型
(1)直接赋值
(2)方法传参
(3)方法返回
二、动态绑定
三、方法重写
四、重写和重载的区别
1.重写:也称方法覆盖(overReading),方法重写是对父类的函数进行重新定义
方法重载允许多个同名函数存在,函数中具有不同的参数个数或者参数类型。重载(overloading)是一个类中多态性的表现。
(1)概念:方法名称、返回值类型、参数的类型及个数完全相同
(2)范围:继承关系
(3)限制:被覆写的方法不能拥有比父类更严格的访问控制权限
2.重载:让类以统一的方式处理不同类型数据的一种手段
在Java中,子类可以继承父类中的方法,而不需要重新编写相同的方法。但有时候子类不想原封不动的继承父类的方法,想做一些修改,就需要采用方法的重写。
(1)概念:方法名称相同,参数的类型及个数不同
(2)范围:一个类
(3)限制:没有权限要求
五、多态
1.在JAVA中,要想使用多态机制,要搭配使用向上转型、动态绑定、方法重写这三种语法,缺一不可,必须也得搭配继承才能使用多态
如果抛开JAVA来说,有些其他的编程语言,体现多态的时候不需要依托继承,或者也不需要依托向上转型、方法重写和动态绑定
C++中的“静态多态”(模板)或者Pathon的多态,其实和这些语法特性没啥关系

class Shape{
    public void draw(){
    }
}
class Cycle extends Shape{
    @Override
    public void draw(){
        System.out.println("○");
    }
}
class Rectangle extends Shape {
    @Override
    public void draw (){
        System.out.println("矩形");
    }
}
class flower extends Shape  {
    @Override
    public void draw(){
        System.out.println("❀");
    }
}
public class Test {
    public static void main(String[] args) {
        Shape shape1 = new flower();
        Shape shape2 = new Cycle();
        Shape shape3 = new Rectangle();
        drawMap(shape1);
        drawMap(shape2);
        drawMap(shape3);
    }

    private static void drawMap(Shape shape) {
        shape.draw();
    }
}

上面是类的实现者,下面是类的调用者
3. 多态的好处
(1)第一个好处(本质)
多态这种设计思想,本质上是“封装”的更进一步,封装的目的是为了让类的使用者不需要知道类的实现细节,就能使用,但是使用者仍然需要知道这个类是啥类型.
使用多态的话,此时类的使用者,不仅不需要知道类的实现细节,也不需要知道这个类具体是啥类型,只要知道这个类有一个draw方法就可以了,这个时候类的使用者知道的信息更少,使用成本就更低.
(2)第二个好处,方便扩展.
未来如果需要新增一个形状,创建一个新的子类即可,并且让子类也去重写这个draw方法,类的调用者这里的代码不需要做出任何修改/或者只做出很小的修改
(3)第三个好处,减少一些分支语句(减少if / else switch / case)
如果不使用多态,实现同样的逻辑,可能就比较复杂了.
六、向下转型
1.大部分使用的场景都是向上转型,结合多态来使用的,向下转型用的不多,只是在一些特定场景下才会用到,把父类引用转成子类引用,向下转型必须得保证操作是合理的,否则可能会存在问题.

Animal animal2 =new Bird();
//这个向下转型操作就是非法的,虽然编译能通过,但是运行时会存在问题
Cat  cat2 =  (Cat)animal2;

2.其实向下转型是存在限制的,不是随便就能转.其实就相当于向上转型的逆过程.
通过向上转型得到的父类的引用,可以借助向下转型还原回原来的类型.
虽然是用的不多,但还是有特殊情况用到的
3.向下转型的应用场景:
有些方法只是在子类中存在,但是父类中不存在,此时使用多态的方式就无法执行到对应的子类的方法了,就必须把父类引用先转回成子类的引用(向下转型),然后再调用对应的方法.
可以在向下转型之前,先做出判定,判定当前的父类的引用到底是不是指向该子类,如果不是就不进行向下转型.
instanceof
4.对象之间的比较有三种形式:
5.(1)比较值 例如String, equals(equals 也是Object(祖宗类)类的一个方法.)
(2)比较身份 ==
(3)比较类型 instanceof
6.StringBuilder的equals进行比较,StringBuilder这个类自身没有重写equals,使用equals 的时候其实是调用了Object默认的那个equals方法.执行的行为就是 ==
如果想比较两个StringBuilder的内容,可以把 StringBuilder 先 toString转成String,再使用String的equals 就可以了.
7.不要在构造方法中调用其他可能被重写的方法
8.方法创建是很早,类被加载的时候就有方法了,属性的创建才是跟随实例的,创建实例是很后面的事情(new )
父类的这个实例其实本质上还是子类实例的一个部分.,this 就是指向子类的实例
9.抽象类和接口 搭配多态使用的重要的语法特性.
抽象类、接口 搭配多态来使用的.
抽象的反义词是 具体
Java中使用abstract关键字来描述抽象类和抽象方法
抽象类本身就是用来表示一个不太具体的概念,抽象方法就更不具体,里面都没有实质的实现.
10.abstract关键字存在的意义,就是让程序员明确的告诉编译器,这个类就是一个抽象的类,不应该进行实例化,于是编译器就要做好相关的检查工作.
类似于这样的检查机制,其实很常见.@Override 也是同理
11.接口
(1)接口是抽象类的更进一步(比抽象类还抽象)
抽象类只是不能实例化,但是其他各个方面都和普通的类差不多,接口就更抽象了,不光不能实例化,同时也不具备类的各种特性
(2)接口中也可以放抽象方法,这里的抽象方法不必写abstract关键字(写或者不写,都是抽象方法)接口中不能放普通的方法.
(3)接口中也不能放普通的属性,只能放public static final修饰的属性.
(4)接口不能继承自其它的类,但是可以继承自其它的接口,接口不能被类继承,而是被其它的类"实现”.
12.抽象类和接口的对比:
(1)抽象类和普通的类差不多,只是不能实例化,而接口和普通的类之间相距甚远(包含的属性,方法,和其他类的关系)
(2)一个类只能继承自一个抽象类,但是一个类可以同时实现多个接口
13.为什么要发明接口这样的语法?
解决Java中不能多继承的问题
Java的继承是单继承,有些场景下多继承是有用的,Java中可以通过继承一个类,实现多个接口的方式来完成类似于多继承的效果(例如,C++或者Python支持多继承的)
14.接口存在的意义:
既能够实现类似于多继承的效果同时又能规避多继承带来的问题

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值