继承和多态

简介: 继承和多态

一.关于继承

1.1继承的概念:

继承 (inheritance) 机制 :是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特 性

的基础上进行 扩展,增加新功能 ,这样产生新的类,称 派生类 。继承呈现了面向对象程序设计的层次结构, 体现了

由简单到复杂的认知过程。继承主要解决的问题是: 共性的抽取,实现代码复用 。其中,被继承的类称为父类、超类,基类,继承的类称为派生类或者子类

1.2关于继承中子类方法调用的是父类成员还是子类成员

1.2.1关于成员属性:①对于 不同名的成员属性 ,先访问子类中的属性,如果子类中不存在该属性,那么再去访问父类中的该属性,父类中不存在则报错。

②对于 同名的成员属性 ,子类方法不能直接访问父类中的同名成员属性,直接访问的是子类新增的成员属性。那我们如何去访问父类中的同名成员属性呢?引 入super关键字,使用super.属性的方式对父类同名成员属性的访问和调用

1.2.2关于成员方法:①如果在子类中定义了权限修饰符、返回值、方法名、参数列表以及参数列表顺序均和父类中方法相同的方法,那我们称 该方法为父类方法的重写方法 ,我们在子类中调用该方法,我们只能直接调用子类重写的方法,如果我们想去调用父类重写之前的方法,我们同样需要 引用super关键字(super.成员方法()) 。

②对于子 父类定义了不同的方法, 那么我们同样还是先在子类中进行访问,再去父类中进行访问,如果子父类中均找不到该方法,则报错。

③如果子类和父类中定义了 同名但参数列表不同的方法 ,则两者的关系为方法的重载,根据参数列表的不同编译器选择调用哪个方法。

1.3关于super关键字

1.super关键字不能单独使用,必须使用super.成员变量或者super.成员方法的方式进行调用。

2.super关键字只能在非静态成员方法中使用

3.在子类方法中访问父类的成员变量和方法

1.4关于子类构造器的声明

①如果父类中没有显式定义构造方法,那么子类可以定义也可以不定义构造方法,两者都不会报错

②如果父类中声明了无参的构造方法,子类中同样可以定义也可以不定义构造方法,同样不会报错

③父类构造器中显式定义了有参的构造方法,子类中必须显式声明super(参数1,参数...)这样与父类构造方法中同参数的构造方法否则会报错。

关于子类构造方法的调用原理如下:

cc5d2eed37a344769a4a38b8de006cb0.png

super和this

【 相同点 】

1. 都是 Java 中的关键字

2. 只能在类的非静态方法中使用,用来访问非静态成员方法和字段

3. 在构造方法中调用时,必须是构造方法中的第一条语句,并且不能同时存在

【 不同点 】

1. this 是 当前对象的引用,当前对象即调用实例方法的对象 , super相当于是子类对象中从父类继承下来部分成员的引用

2. 在非静态成员方法中, this用来访问本类的方法和属性 , super用来访问父类继承下来的方法和属性

3. 在构造方法中: this(...)用于调用本类构造方法, super(...)用于调用父类构造方法,两种调用不能同时在构造

方法中出现

4. 构造方法中 一定会存在super(...)的调用,用户没有写编译器也会增加 , 但是this(...)用户不写则没有

1.在类加载时会调用静态代码块,执行顺序为先父类后子类(静态代码块只在类加载过程中执行一次,与创建多少个对象无关)

2.构造方法:在有继承关系的构造方法中,实例代码块会被拷贝到第一条语句之前(第一条默认语句之后),其表现为一般先调用父类实例代码块,再调用父类构造方法,再调用子类实例代码块,再调用子类构造方法。我们每创建一个对象,都会调用一次构造方法。



59be2152f7054d29af51434839bea931.png

819649888d9f40689abc279b962ffe99.png


如图,当我们加载完父类和子类的信息后(完成了静态代码块的调用),我们即使在子类构造方法的第一句调用this(子类其他构造方法),仍然会先执行该语句,执行完该语句后再去调用子类的实例代码块。


我们最后的结论是:

1、父类静态代码块优先于子类静态代码块执行,且是最早执行

2、父类实例代码块和父类构造方法紧接着执行

3、子类的实例代码块和子类构造方法紧接着再执行

4、第二次实例化子类对象时,父类和子类的静态代码块都将不会再执行

protected关键字

notes:

protected修饰的成员属性或者方法,只能在其子类创建的main方法中被访问,其余无论在其他子类或者非子类

的main方法中创建的另一个子类的对象仍然编译不通过。

例子:

3745f01fdca34e04b97e95d52907b628.png

继承和组合

和继承类似 , 组合也是一种表达 类之间关系的方式 , 也是能够达到 代码重用的效果 。组合并没有涉及到特殊的语法

( 诸如 extends 这样的关键字 ), 仅仅是 将一个类的实例作为另外一个类的字段 。

继承表示对象之间是 is-a 的关系 ,比如:狗是动物,猫是动物

组合表示对象之间是 has-a 的关系 ,比如:汽车

.多态及多态实现的条件

多态的概念: :通俗来说,就是多种形态, 具体点就是去完成某个行为,当不同的对象去完成时会产生出不同 的状

态。

多态实现的条件:

1. 必须在 继承体系下

2. 子类必须要 对父类中方法进行重写

3. 通过父类的引用 调用重写的方法

多态体现:在代码运行时,当传递 不同类对象 时,会 调用对应类中的方法 。

需要解释的是:在调用实现多态的方法时,如果通过 父类调用实现多态的方法 ,在编 译阶段并不知道调用的实际是哪个方法 ,只有在程序运行起来了才知道调用的是哪个方法。

b93d5cdc027a4da994f8547a4eda5010.png

c398f96623e14014888978f4ef32ed71.png

当类的调用者在编写 eat 这个方法的时候 , 参数类型为 Animal ( 父类 ), 此时在该方法内部并 不知道 , 也不关注 当前的

a 引用指向的是哪个类型 ( 哪个子类 ) 的实例 . 此时 a 这个引用调用 eat 方法可能会有多种不同的表现 ( 和 a 引用的实例

相关 ), 这种行为就称为 多态

方法的重写

重写 (override) :也称为覆盖。重写是子类对父类 非静态、非 private 修饰,非 fifinal 修饰,非构造方法等的实现过程

进行重新编写 , 返回值和形参都不能改变 。 即外壳不变,核心重写! 重写的好处在于 子类可以根据需要,定义特定

于自己的行为。 也就是说子类能够根据需要实现父类的方法。

【 方法重写的规则 】

1.子类在重写父类的方法时,一般必须 与父类方法原型 一致: 返回值类型 方法名 ( 参数列表 ) 要完全一致

2.被重写的方法返回值类型可以不同,但是必须是 具有父子关系 的

3. 访问权限不能比父类中被重写的方法的访问权限更低。 例如:如果父类方法被 public 修饰,则子类中重写该方

法就不能声明为 protected

4.父类被 static 、 private 修饰的方法、final、构造方法都不能被重写。

5.重写的方法 , 可以使用 @ Override 注解来显式指定 . 有了这个注解能帮我们进行一些合法性校验 . 例如不小心

将方法名字拼写错了 ( 比如写成 aet), 那么此时编译器就会发现父类中没有 aet 方法 , 就会编译报错 , 提示无法

构成重写

对静态、private、final修饰的方法以及构造方法不能实现重写的原因解释:

1.static:在实现多态时,需要 基类的引用调用被重写的方法 ,所以被重写的方法 需要this引用才能确定调用那个类中的方法 (实现多态时,编译器无法通过父类的 参数判断调用哪个子类实现重写的方法 ,只有在运行时 基类的引用指向具体的对象才能确定调用那个类中被重写的方法 ),而被static修饰的方法 没有this引用,无法实现多态,那么实现方法的重写毫无意义,被编译器禁止 。

2.private:private修饰的类 无法被子类访问 ,自然也就没办法实现 对父类方法的重写 。

3.final:编译器规定被final修饰的方法不能实现重写。

4.构造方法:构造方法作用在创建对象时,由编译器调用,将 对象初始化完整 ,如果子类对父类的构造方法进行重写, 父类构造方法没有调用 ,父类对象不完整, 无法实现多态 ,而当对象创建完整之后,构造方法已经完成调用,也无法实现多态。


f5600ff1075f4729b1a47056deb340e5.png

向上和向下转型

向上转型

向上转型:实际就是 创建一个子类对象,将其当成父类对象来使用。

语法格式:父类类型 对象名 = new 子类类型 ()

6857b803689f4f8e9cb8f53a86aafdc7.png

animal 是 父类类型,但可以引用一个子类对象,因为是从小范围向大范围的转换

在我们日常的认知中,可以这样考虑:猫(子类)是动物(父类),狗(子类)是动物(父类)

向上转型的优点:让代码实现更简单灵活。

向上转型的缺陷:不能调用到子类特有的方法

向下转型

将一个子类对象经过向上转型之后当成父类方法使用,再无法调用子类的方法,但有时候可能需要调用子类特有的

方法,此时:将父类引用再还原为子类对象即可,即向下转换。

多态的优缺点

看如下代码:

68716ecc7d8f428abb63afb604e98222.png


相关文章
|
6月前
|
C#
初识继承和多态
初识继承和多态
|
6月前
|
存储 设计模式 编译器
【C++】继承和多态常见的问题
【C++】继承和多态常见的问题
|
6月前
|
安全 Java 编译器
继承与多态
继承与多态
|
6月前
面向对象编程:类、对象、继承与多态
面向对象编程:类、对象、继承与多态
39 0
|
编译器 程序员 C++
【C++】继承和多态
【C++】继承和多态
437 3
|
编译器
【多态-动态绑定-向上转型-抽象类】
【多态-动态绑定-向上转型-抽象类】
46 0
|
编译器 C++
C++类和对象-继承&多态
C++类和对象-继承&多态
75 0
|
Java
类的继承多态
类的继承多态
78 0
总结继承和多态的一些问题
本人学习了多态和继承后的一些问题,解答出来并总结,有些是容易搞混的概念。
总结继承和多态的一些问题
继承与多态(1)
继承与多态(1)
101 0
继承与多态(1)