Java_继承和多态

news/2024/7/24 9:23:40 标签: java, 开发语言

文章目录

  • 前言
  • 继承
    • 继承语法
    • 继承总结
    • super指定访问父级
    • 子类构造方法
    • super和this
    • 再谈初始化(执行顺序)
    • protected 关键字
    • 继承方式
    • final 关键字
    • 继承与组合
  • 多态
    • 动态绑定与静态绑定
    • 多态实现条件
    • 重写

前言

适合复习看

继承

继承语法

在这里插入图片描述

java">修饰符 class 子类 extends 父类 {
// ...
}

子类会将父类中的成员变量或者成员方法继承到子类中了

子类继承父类之后,必须要新添加自己特有的成员,体现出与基类的不同,否则就没有必要继承了

继承总结

在子类方法中 或者 通过子类对象访问成员时:

  1. 如果访问的成员变量子类中有,优先访问自己的成员变量。
  1. 如果访问的成员变量子类中无,则访问父类继承下来的,如果父类也没有定义,则编译报错。
  1. 如果访问的成员变量与父类中成员变量同名,则优先访问自己的

成员变量访问遵循就近原则,自己有优先自己的,如果没有则向父类中找


子类中访问父类的成员方法时:

  1. 通过子类对象访问父类与子类中不同名方法时,优先在子类中找,找到则访问,否则在父类中找,找到则访问,否则编译报错。
  1. 通过派生类对象访问父类与子类同名方法时,如果父类和子类同名方法的参数列表不同(重载),根据调用方法视传递的参数选择合适的方法访问,如果没有则报错

super指定访问父级

Java提供了super关键字,该关键字主要作用:在子类方法中访问父类的成员。

在这里插入图片描述

注意

  1. 只能在非静态方法中使用
  2. 在子类方法中,访问父类的成员变量和方法

子类构造方法

父子父子,先有父再有子,即:子类对象构造时,需要先调用基类构造方法,然后执行子类的构造方法

在子类构造方法中,并没有写任何关于基类构造的代码,但是在构造子类对象时,先执行基类的构造方法,然后执行子类的构造方法,因为:子类对象中成员是有两部分组成的,基类继承下来的以及子类新增加的部分 。父子父子肯定是先有父再有子,所以在构造子类对象时候 ,先要调用基类的构造方法,将从基类继承下来的成员构造完整,然后再调用子类自己的构造方法,将子类自己新增加的成员初始化完整。

注意:

  1. 若父类显式定义无参或者默认的构造方法,在子类构造方法第一行默认有隐含的super()调用,即调用基类构
    造方法
  2. 如果父类构造方法是带有参数的,此时需要用户为子类显式定义构造方法,并在子类构造方法中选择合适的
    父类构造方法调用,否则编译失败。
  3. 在子类构造方法中,super(…)调用父类构造时,必须是子类构造函数中第一条语句。
  4. super(…)只能在子类构造方法中出现一次,并且不能和this同时出现(构造方法 this() 和 super() 都必须在第一行,所以不能同时出现)

super和this

【相同点】

  1. 都是Java中的关键字
  2. 只能在类的非静态方法中使用,用来访问非静态成员方法和字段
  3. 在构造方法中调用时,必须是构造方法中的第一条语句,并且不能同时存在

【不同点】

  1. this是当前对象的引用,当前对象即调用实例方法的对象,super相当于是子类对象中从父类继承下来部分成
    员的引用
  2. 在非静态成员方法中,this用来访问本类的方法和属性,super用来访问父类继承下来的方法和属性
  3. 在构造方法中:this(…)用于调用本类构造方法,super(…)用于调用父类构造方法,两种调用不能同时在构造
    方法中出现
  4. 构造方法中一定会存在super(…)的调用,用户没有写编译器也会增加,但是this(…)用户不写则没有

再谈初始化(执行顺序)

在这里插入图片描述

1、父类静态代码块优先于子类静态代码块执行,且是最早执行
2、父类实例代码块和父类构造方法紧接着执行
3、子类的实例代码块和子类构造方法紧接着再执行
4、第二次实例化子类对象时,父类和子类的静态代码块都将不会再执行

使用static关键字定义的代码块,一般用于初始化静态成员属性;静态代码块不管生成多少个对象,其只会执行一次,且是最先执行的;然后就地初始化普通(实例)代码块初始化看书写的先后顺序,写在前面的先执行;然后才是构造方法初始化。

protected 关键字

在这里插入图片描述

子类 就是 基类(父类)的派生类(子类)

protected修饰的 可以调用 在不同包中的,继承该包的类的子类


注意:父类中private成员变量虽然在子类中不能直接访问,但是也继承到子类中了

什么时候下用哪一种呢?
我们希望类要尽量做到 “封装”, 即隐藏内部实现细节, 只暴露出 必要 的信息给类的调用者.
因此我们在使用的时候应该尽可能的使用 比较严格 的访问权限. 例如如果一个方法能用 private, 就尽量不要用 public.

另外, 还有一种 简单粗暴 的做法: 将所有的字段设为 private, 将所有的方法设为 public. 不过这种方式属于是
对访问权限的滥用, 还是更希望同学们能写代码的时候认真思考, 该类提供的字段方法到底给 “谁” 使用(是类内部自己用, 还是类的调用者使用, 还是子类使用)

继承方式

Java中只支持以下几种继承方式:
在这里插入图片描述

注意:Java中不支持多继承。

时刻牢记, 我们写的类是现实事物的抽象. 而我们真正在公司中所遇到的项目往往业务比较复杂, 可能会涉及到一系列复杂的概念, 都需要我们使用代码来表示, 所以我们真实项目中所写的类也会有很多. 类之间的关系也会更加复杂.

但是即使如此, 我们并不希望类之间的继承层次太复杂. 一般我们不希望出现超过三层的继承关系. 如果继承层次太多, 就需要考虑对代码进行重构了.
如果想从语法上进行限制继承, 就可以使用 final 关键字

final 关键字

final关键可以用来修饰变量、成员方法以及类。

  1. 修饰变量或字段,表示常量(即不能修改)
java">final int a = 10;
a = 20; // 编译出错
  1. 修饰类:表示此类不能被继承
java">final public class Animal {
...
}
public class Cat extends Animal {
...
} 
// 编译出错
//Error:(3, 27) java: 无法从最终com.bit.Animal进行继承

我们平时是用的 String 字符串类, 就是用 final 修饰的, 不能被继承

  1. 修饰方法:表示该方法不能被重写

继承与组合

和继承类似, 组合也是一种表达类之间关系的方式, 也是能够达到代码重用的效果。组合并没有涉及到特殊的语法
(诸如 extends 这样的关键字), 仅仅是将一个类的实例作为另外一个类的字段。

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

组合表示对象之间是has-a的关系,比如:汽车和其轮胎、发动机、方向盘、车载系统等的关系就应该是组合,因为汽车是有这些部件组成的

java">class Student2 {

}
class Teacher {

}

class School {

    public Student2[] student2s = new Student2[10];
    public Teacher[] teachers = new Teacher[5];
    //不用继承就能使用"父类"

}

注意组合和继承都可以实现代码复用,应该使用继承还是组合,需要根据应用场景来选择,一般建议:能用组合尽量用组合

多态

动态绑定与静态绑定

多态的本质就是利用动态绑定,不同对象执行的效果也不一样

动态绑定
(假设,有一父类和一子类,里面都有除了内容外完全相同的eat方法)
创建父类类型的引用A,让A指向子类(new子类),然后用A调用eat方法时
编译的时候 认为 还是调用了父类的eat方法, 不过运行的时候 绑定到了子类当中

静态绑定
编译的时候,已经确定了调用那个方法了
(例如,类中有不带参数的构造方法A和带参数的构造方法B,调用构造方法时,带参数那就是执行构造方法B,不带参数则执行构造方法A)

多态实现条件

java中要实现多态,必须要满足如下几个条件,缺一不可:

  1. 必须在继承体系下
  2. 子类必须要对父类中方法进行重写
  3. 通过父类的引用调用重写的方法

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

父类:

java">class Animal {
    private String name;
    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return this.name;
    }
    public void eat() {
        System.out.println("eat");
    }
}

两个子类:

java">class Cat extends Animal {
    Cat(String name) {
        super.setName(name);
    }
    @Override//对父类的eat进行重写
    public void eat() {
        System.out.println(super.getName() + "吃猫粮");
    }
}
class Dog extends Animal {
    Dog(String name) {
        super.setName(name);
    }
    @Override//对父类的eat进行重写
    public void eat() {
        System.out.println(super.getName() + "吃狗粮");
    }
}

测试:

java">class test {
    public static void main(String[] args) {
        Animal animal = new Cat("猫猫");//向上转型,把子类传给父类的类型
        animal.eat();

        animal = new Dog("狗子");
        animal.eat();
        //打印为:
        //猫猫吃猫粮
        //狗子吃狗粮
    }
}

重写

重写(override):也称为覆盖。重写是子类对父类非静态、非private修饰,非final修饰,非构造方法等的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法

方法重写规则:

  1. 子类在重写父类的方法时,一般必须与父类方法原型一致: 返回值类型 方法名 (参数列表) 要完全一致
  2. 被重写的方法返回值类型可以不同,但是(返回类型)必须是具有父子关系的
  3. 访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类方法被public修饰,则子类中重写该方
    法就不能声明为 protected
  4. 父类被static、private修饰的方法构造方法不能被重写
  5. 重写的方法, 可以使用 @Override 注解来显式指定. 有了这个注解能帮我们进行一些合法性校验. 例如不小心将方法名字拼写错了 (eat比如写成 aet), 那么此时编译器就会发现父类中没有 aet 方法, 就会编译报错, 提示无法
    构成重写

http://www.niftyadmin.cn/n/5171105.html

相关文章

toolbox-app 升级出现无法识别已安装app

toolbox-app升级后无法识别已安装的app。 因为toolbox-app 2.x版本升级后需要执行原有安装app的迁移。若是不执行迁移,新版本的toolbox-app是无法识别已安装app。 这时卸载新版本的toolbox-app,安装回1.x的版本,就可以,若是执行更…

计算机网络期末复习-Part3

1、rdt1.0,rdt2.0,rdt3.0的底层信道模型 RDT 1.0: 完全可靠的底层信道,没有比特差错,也没有分组丢失。 RDT 2.0: 具有比特差错的底层信道,有比特差错,但没有分组丢失。 RDT 3.0: 具有差错和丢包的底层信道…

吴恩达《机器学习》7-1->7-4:过拟合问题、代价函数、线性回归的正则化、正则化的逻辑回归模型

一、过拟合的本质 过拟合是指模型在训练集上表现良好,但在新数据上的泛化能力较差。考虑到多项式回归的例子,我们可以通过几个模型的比较来理解过拟合的本质。 线性模型(欠拟合): 第一个模型是一个线性模型&#xff0…

巨好用又实用的18款3dMax插件!

3dMax是一款功能强大的 3D 软件,具有建模、动画、粒子动力学等许多强大功能。但并不是每个人都能有效地利用max的每一个功能,例如,很多人发现3dmax粒子流太难使用,3ds max蒙皮工具也是如此。 这让我们一些专业的开发公司或个人和…

ElasticSearch文档分析

ElasticSearch文档分析 包含下面的过程: 将一块文本分成适合于倒排索引的独立的 词条将这些词条统一化为标准格式以提高它们的“可搜索性”,或者 recall 分析器执行上面的工作。分析器实际上是将三个功能封装到了一个包里: 字符过滤器 首先&a…

对称密钥加密与非对称密钥加密:原理与应用

在信息安全领域,对称密钥加密和非对称密钥加密是两种重要的加密方法,它们各有特点,适用于不同的场景。本文将详细介绍这两种加密方法的原理,并通过实例说明其应用,同时阐述在报文传输过程中,何时使用对称密…

JAVA序列、反序列化及漏洞

摘要 介绍序列化、反序列化背景;java实现,以及存在的漏洞和解决方案 一、背景 java序列化将java对象转换为字节流,反序列化根据字节流创建java对象(不通过constructor)。当然,反序列化过程中也会源源不断的…

国际上有影响的10位城市设计师 优漫教育

这是以一篇网络文章为主并综合一些资料整理的“国际上有影响的10位城市设计师”。这10位城市设计师生活的时间跨度非常大,他们中间除了雅各布斯以外,都是建筑师、城市规划师或景观设计师,或有相关的教育背景,从一个侧面反映了城市…