JavaSE学习之--继承和多态(一)

简介: JavaSE学习之--继承和多态

💕"越是不思考的人,越不愿倾听别人说话。"💕

作者:Mylvzi

文章主要内容:JavaSE学习之--继承和多态

一.继承(inheritance)

1.为什么要有继承

   我们前面学过类,类是对现实事物的抽象化处理,而通过类实例化的对象则可以用来表示事物。在现实生活中,事物与事物之间有着千丝万缕的联系,最常见的一种就是“父子关系”,儿子会继承父亲的很多特征,而自己又有自己独特的特征;再比如狗和猫都是动物,都具有动物的一些属性,如年龄,性别,毛发颜色等等等等;为了在计算机中表示这种关系,创建了“继承”!

2.继承的概念

 继承(inheritance):就是对事物共性的抽取,从而实现代码复用;

从和实际生活的联系来讲,继承就是将事物的共同属性抽取出来,用一个大类来表示,比如一个父亲有多个孩子,这些孩子都具有某些共性,如年龄,性别,将这些共同属性抽取出来,创建一个新类“Child”;

从代码实现来讲,继承关系的存在实现了代码的复用,子类继承了父类的属性和方法,大大提高效率;

补充:

       其实Java中有很多这种“对共性进行抽取从而达到代码复用”的思路,比如前面学过的类变量,就是所有对象的共同属性的抽取

对象的共性-->静态成员变量

类的共性-->继承extends

3.继承的语法及代码实现

// 父类
class Animal {
    String name;
    int age;
    public void eat() {
        System.out.println(name+"i am eating!!!");
    }
    public void sleep() {
        System.out.println(name+"i am sleeping!!!");
    }
}
// 子类
// 通过关键字extends表示此类继承于父类
class Dog extends Animal {
    public void bark() {
        System.out.println(name+"汪汪叫!!!");
    }
}
class Cat extends Animal {
    public void mew() {
        System.out.println(name+"喵喵叫!!!");
    }
}
public class Test {
    public static void main(String[] args) {
        Dog dog1 = new Dog();
        dog1.name = "初一";
        dog1.age = 3;
        // dog1的成员变量中并没有name和age,但却能引用,则一定继承于父类
        System.out.println(dog1.name);
        System.out.println(dog1.age);
        dog1.eat();
        dog1.sleep();
        dog1.bark();
    }
}

总结:

1. 继承关键字-->extends,格式为:class 子类 extends 父类

2.子类会继承父类的成员和方法,实例化对象之后直接通过对象就能访问

3.子类继承父类的成员和方法之后,还需要有不同于父类的成员或方法(比如Dog类中的bark)

4.在子类中访问父类成员-->super关键字

 1.子类中访问父类成员

11.不存在同名成员变量

class Base {
    int a;
    int b;
    public void method1() {
        System.out.println("hello1");
    }
}
class Derived extends Base {
    int c;// 类特有的
    public void method2() {
        a = 30;// 访问父类继承下来的变量
        b = 20;// 访问父类继承下来的变量
        c = 10;// 访问子类自己的变量
    }

1.2存在同名成员变量

class Base {
    int a;
    int b;
    public void method1() {
        System.out.println("hello1");
    }
}
class Derived extends Base {
    int a;// 和父类同名
    int c;// 子类特有的
    public void method2() {
        a = 30;// 究竟是给父类赋值,还是给子类赋值?
        b = 20;
        c = 10;
    }

1.3在子类中访问成员方法

class Base {
    int a;
    int b;
    public void method1() {
        System.out.println("hello1");
    }
}
class Derived extends Base {
    int c;
    // 和父类的方法构成了重载
    public void method1() {
        System.out.println("hello2");
    }
    // 子类特有的方法
    public void method2() {
        System.out.println("hello2");
    }
}
public class TestDemo1 {
    public static void main(String[] args) {
        Derived p1 = new Derived();
        p1.method1();
        p1.method2();
        // 输出hello1  hello2
        // 证明先执行子类的方法
        // 既不属于子类,又不属于父类,编译失败
//        p1.method3();
    }
}

总结:

       1.父类,子类存在同名的成员变量,成员方法,优先访问子类的,子类中没有再去父类中寻找,寻找不到就编译报错

       2.子类和父类可构成方法的重载,将参数列表设置为不同,在调用时通过传参调用不同的方法!

1.3 那如何在子类中访问父类的成员呢?通过super关键字!

 由于设计不好或者特殊场景需要,需要在子类中访问父类成员,但如果出现重名编译器会优先访问子类中的,并不会访问父类中的成员变量,那该怎么解决呢?Java中提供了关键字super,该关键字的作用是-->在子类方法中访问父类成员变量

class Base {
    int a;
    int b;
    public void method1() {
        System.out.println("hello1");
    }
}
class Derived extends Base {
    int a;
    int b;
    int c;
    public void method1() {
        a = 10;// 等价于this.a
        b = 20;// 等价于this.b
        // 通过super关键字来访问父类成员
        super.a = 30;
        super.b = 40;
    }

super访问方法:

class Derived extends Base {
    int a;
    int b;
    int c;
    public void method1() {
        System.out.println("hello2 这是子类方法");
    }
    public void method2() {
        a = 10;// 等价于this.a
        b = 20;// 等价于this.b
        // 通过super关键字来访问父类成员
        super.a = 30;
        super.b = 40;
        method1();// 输出hello2
        super.method1();// 输出hello1

总结:

1.super关键字的作用就是在子类方法中访问父类成员变量和方法!

2.super只能在子类的非静态方法中使用,因为super主要用来访问并实例化父类中的实例变量,而实例变量必须依赖于对象,静态方法不依赖于对象,所以super不能在子类的静态方法中使用! (super可以访问父类的类变量,但是不建议,更建议通过类名)

3.super只是关键字,提升了代码的可读性,并不代表对父类成员的引用!

1,4子类的构造方法

 构造方法是用来初始化成员变量的一种特殊方法,其在对象的创建过程中就会被调用,而且即使你不写构造方法,编译器会默认添加一个不带参数的构造方法,给你的成员变量赋初始值;在子类中,既有从父类继承过来的成员变量,又有自己独有的成员变量,那在构造方法中赋值的顺序有没有要求呢?答案是有的,先上结论:

 必须先对父类成员变量进行初始化才能对子类成员变量进行初始化!

也就是说在子类的构造方法中会先调用对父类的构造方法,再对子类的成员变量进行初始化。

class Base {
    int a;
    int b;
    // 父类的构造方法
    public Base() {
        System.out.println("父类的构造方法!!!");
    }
}
class Derived extends Base {
    int a;
    int b;
    int c;
    public Derived() {
        // 会默认有一个不带参数的super()
        // 代表父类的初始化
        System.out.println("子类的构造方法!!!");
    }
}

注意事项:

super()就代表调用父类的构造方法!!!

和this();的含义一样!!!

1.super只能放在第一行,放在其他行就报错

2.如果父类的构造方法带参数,则在子类中调用父类的构造方法时也要带参数!(可以快速创建)
// 带参数的父类的构造方法
    public Base(int a, int b) {
        this.a = a;
        this.b = b;
        System.out.println("这是父类构造方法");
    }
    // 子类中的构造方法
    // 必须先对父类成员变量进行初始化
public Derived(int a, int b, int a1, int b1, int c) {
        super(a, b);// 必须放在第一行
                    // 且必须要传参数
        this.a = a1;
        this.b = b1;
        this.c = c;
        System.out.println("这是子类构造方法");
    }

注意:如果父类提供的是一个显式的构造方法,则在子类中必须利用super进行传参!!!

如果父类的构造方法不带参数,在子类的构造方法中可以不写,因为系统会自动提供一个不带参数的super();

3.在子类的构造方法中super和this不能同时出现,且super只能出现一次

   在构造方法那一节我们学过,对于一个类的构造方法,如果要使用this来调用当前类的其他构造方法,则this只能放在第一行,那如果我既想通过super来初始化父类的成员变量,又想通过this调用当前类的其他构造方法该怎么办?答案是没有办法,如果同时拥有会冲突,只能保证他们不能同时存在!

 为什么只能出现一次呢?原因在于继承结构的逻辑链!在继承结构中,子类会先调用父类的构造方法,再执行自身的初始化逻辑,这种执行顺序是线性的,不需要多次进行父类的初始化!

1.5super和this的比较

 我们学过super和this,发现他们有很多相同点,比如都是通过.操作符来访问变量或方法,那他们有哪些异同点呢?下面来总结一下:

相同点:

1.都是Java中的关键字。

2.都只能在非静态方法中访问非静态成员变量或非静态方法

3.在构造方法中调用时,都必须写在第一行,所以super和this不能同时使用;

不同点:

1.this代表当前对象的引用,用于访问当前对象的成员变量及方法;super是用来访问从父类继承的成员或方法。或者说super是引用对象从父类继承部分的引用

2.在构造方法中,super会有默认的对父类的构造方法(先有父后有子),而this并没有默认的构造方法。

3.this(......) 代表当前对象的构造方法,super(.......)代表父类的构造方法,两者不能同时出现

JavaSE学习之--继承和多态(二)+https://developer.aliyun.com/article/1413490



目录
相关文章
|
5月前
|
Ubuntu NoSQL 编译器
在Ubuntu 20.04上构建RISC-V和QEMU环境
以上的步骤只是开始,RISC-V的世界里有无数的未知等待你去探索。加油,勇敢的探险家。
300 18
|
10月前
|
存储 JSON 开发工具
三、HarmonyOS NEXT应用开发:ArkTS工程目录结构(Stage模型)
本文介绍了HarmonyOS NEXT应用开发中ArkTS工程的目录结构(Stage模型),包括AppScope、entry、hvigor、oh_modules等主要目录及其作用。重点解析了entry目录下的src > main > resources目录结构,详细说明了base、限定符目录和rawfile的作用,以及如何引用资源文件。
504 1
|
机器学习/深度学习 人工智能 算法
【机器学习】基于YOLOv10实现你的第一个视觉AI大模型
【机器学习】基于YOLOv10实现你的第一个视觉AI大模型
874 0
探讨AC/DC电源模块的可靠性设计和测试方法
探讨AC/DC电源模块的可靠性设计和测试方法
探讨AC/DC电源模块的可靠性设计和测试方法
|
存储 XML 缓存
前端知识笔记(一)———Base64图片是什么?原理是什么?优缺点是什么?
前端知识笔记(一)———Base64图片是什么?原理是什么?优缺点是什么?
339 0
|
缓存 前端开发 JavaScript
企业级应用,开源商城系统-lilishop
LILISHOP商城系统由北京宏业汇成科技有限公司开发,使用JAVA语言开发的企业级电商系统,主推模式为B2B2C(平台、商家、用户),支持商家入驻、商家结算。软件与2021年收录与开源中国,与2021年7月首次升级开源版本。 LILISHOP至力与为大、中、小企业提供高可用、高并发的电商解决方案,协助企业快速构建自己的电商平台。
2021 0
|
小程序 API 开发工具
小程序消息推送入门 (订阅消息推送)
小程序消息推送入门 (订阅消息推送)
1226 0
|
Web App开发 缓存 安全
Discuz历史漏洞分析(三)
Discuz是非常受欢迎的论坛型CMS,但是近年来DZ也爆出了很多经典漏洞,以下分析了几个不同类型的DZ历史漏洞(SQL注入、XSS、任意文件删除、弱加密算法、任意代码执行、HTTP HOST攻击等),提高安全人员的安全意识。
Discuz历史漏洞分析(三)
|
机器学习/深度学习 存储 数据采集