0216-0218复习:继承

news2024/9/24 23:32:42

目录

继承

一、基本介绍

二、示意图

三、基本语法

四、入门案例

父类

子类1

子类2

main方法

五、继承细节

第一条

第二条

第三条

第四条

​编辑 第五条

 第六条

第七条

第八条

第九条

第十条

六、继承本质

七、练习题

第三题

继承

一、基本介绍

继承可以解决代码冗余过高的问题,将两个或多个类中相同的属性和方法提取出来,放在一个类中,称其为父类,子类继承父类,就是继承了这些属性和方法(不需要再次说明),同时,子类中也可以有其特有的属性和方法

二、示意图

三、基本语法


子类 extends 父类{
子类特有的属性和发方法

注意事项:子类中一定要加关键字extends

四、入门案例

父类

package com.hspedu.extend_;

public class Student {//父类
    public String name;
    public int age;
    private double score;

    public void setScore(double score) {
        this.score = score;
    }
    public void showInfo(){
        System.out.println("学生名 " + name + " 年龄 " + age + " 成绩 " + score);
    }
}

子类1

package com.hspedu.extend_;

public class Pupil extends Student{
    public void testing() {
        System.out.println("小学生 " + name + " 正在考小学数学..");
    }
}

子类2

package com.hspedu.extend_;

public class Graduate extends Student{
    public void testing() {//和 Pupil 不一样
        System.out.println("大学生 " + name + " 正在考大学数学..");
    }
}

main方法

package com.hspedu.extend_;

public class Extends01 {
    public static void main(String[] args) {
        Graduate graduate = new Graduate();
        graduate.name = "金角大王";
        graduate.age = 21;
        graduate.testing();
        graduate.setScore(87);
        graduate.showInfo();

        System.out.println("===============");
        Pupil pupil = new Pupil();
        pupil.name = "银角大王";
        pupil.age = 11;
        pupil.testing();
        pupil.setScore(90);
        pupil.showInfo();
    }

}

控制台输出结果

五、继承细节

第一条

子类继承了父类所有的属性和方法,非私有的属性和方法可以在子类直接访问,私有属性不能在子类直接访问,要通过父类的public方法去访问

父类

package com.hspedu.extend_;

public class Base {//父类
    //四个属性,四个访问修饰符
    public int n1 = 100;
    protected int n2 = 200;
    int n3 = 300;
    private int n4 = 400;


    //默认的无参构造器
    public Base() {
        System.out.println("Base()....");
    }
    //四个方法,访问修饰符对应四个属性
    public void test100(){
        System.out.println("test100");
    }
    protected void test200(){
        System.out.println("test200");
    }
    void test300(){
        System.out.println("test300");
    }
    private void test400(){
        System.out.println("test400");
    }

}

子类

package com.hspedu.extend_;

public class Sub extends Base{//子类
    public Sub() {
        System.out.println("Sub()....");
    }
    public void sayOk(){
        //除了private属性和方法之外都可以访问
        
    }

}

子类中不能访问父类中的private属性和方法

要通过父类提供的public方法去访问 

package com.hspedu.extend_;

public class Base {//父类
    //四个属性,四个访问修饰符
    public int n1 = 100;
    public final int n5 = 500;
    protected int n2 = 200;
    int n3 = 300;
    private int n4 = 400;


    //默认的无参构造器
    public Base() {
        System.out.println("Base()....");
    }

    //父类提供一个public方法,子类可以访问父类的private属性
    public int getN4(){
        return n4;
    }

    //四个方法,访问修饰符对应四个属性
    public void test100(){
        System.out.println("test100");
    }
    protected void test200(){
        System.out.println("test200");
    }
    void test300(){
        System.out.println("test300");
    }
    private void test400(){
        System.out.println("test400");
    }
    //父类提供一个public方法,子类可以访问父类的private方法
    public void callTest400(){
        test400();
    }

}
package com.hspedu.extend_;

public class Sub extends Base{//子类
    public Sub() {
        System.out.println("Sub()....");
    }
    public void sayOk(){
        //除了private属性和方法之外都可以访问
        System.out.println(n1 + " " + n2 + " " + n3);
        test100();
        test200();
        test300();
        //test400();
        System.out.println("n4= " + getN4());
        callTest400();//中转
    }

}

package com.hspedu.extend_;

public class ExtendsDetail {
    public static void main(String[] args) {
        //细节说明
        Sub sub = new Sub();
        sub.sayOk();
    }
}

第二条

子类必须调用父类的构造器, 完成父类的初始化


第三条

当创建子类对象时, 不管使用子类的哪个构造器, 默认情况下总会去调用父类的无参构造器, 如果父类没有提供无参构造器, 则必须在子类的构造器中用 super 去指定使用父类的哪个构造器完成对父类的初始化工作, 否则, 编译不会通过

package com.hspedu.extend_;

public class Base {//父类
    //四个属性,四个访问修饰符
    public int n1 = 100;
    public final int n5 = 500;
    protected int n2 = 200;
    int n3 = 300;
    private int n4 = 400;


    //默认的无参构造器
//    public Base() {
//        System.out.println("父类Base()的构造器被调用....");
//    }
    //父类的有参构造器
    public Base(String name, int age){
        System.out.println("父类的(String name, int age)构造器被调用....");
    }

    //父类提供一个public方法,子类可以访问父类的private属性
    public int getN4(){
        return n4;
    }

    //四个方法,访问修饰符对应四个属性
    public void test100(){
        System.out.println("test100");
    }
    protected void test200(){
        System.out.println("test200");
    }
    void test300(){
        System.out.println("test300");
    }
    private void test400(){
        System.out.println("test400");
    }
    //父类提供一个public方法,子类可以访问父类的private方法
    public void callTest400(){
        test400();
    }

}
package com.hspedu.extend_;

public class Sub extends Base{//子类
    public Sub() {
        //super();//隐藏的,创建子类对象的时候会默认调用父类的无参构造器
        super("smith",20);//当父类的无参构造器被覆盖时,用super指定调用父类的构造器
        System.out.println("子类Sub()构造器被调用....");
    }
    //当创建子类对象时, 不管使用子类的哪个构造器, 默认情况下总会去调用父类的无参构造器
    public Sub(String name){
        super("smith",20);
        System.out.println("子类Sub(String name)构造器被调用....");
    }
    public void sayOk(){
        //除了private属性和方法之外都可以访问
        System.out.println(n1 + " " + n2 + " " + n3);
        test100();
        test200();
        test300();
        //test400();
        System.out.println("n4= " + getN4());
        callTest400();//中转
    }

}
package com.hspedu.extend_;

public class ExtendsDetail {
    public static void main(String[] args) {
        //细节说明
        Sub sub = new Sub();
        System.out.println("=========第二个对象==========");
        Sub sub2 = new Sub("jack");
        //sub.sayOk();

    }
}

第四条

如果希望指定去调用父类的某个构造器, 则显式的调用一下 : super(参数列表)

package com.hspedu.extend_;

public class Base {//父类
    //四个属性,四个访问修饰符
    public int n1 = 100;
    public final int n5 = 500;
    protected int n2 = 200;
    int n3 = 300;
    private int n4 = 400;


    //默认的无参构造器
    public Base() {
        System.out.println("父类Base()的构造器被调用....");
    }
    //父类的有参构造器,两个参数
    public Base(String name, int age){
        System.out.println("父类的(String name, int age)构造器被调用....");
    }
    //一个参数的构造器
    public Base(String name){
        System.out.println("父类的(String name)构造器被调用....");
    }

    //父类提供一个public方法,子类可以访问父类的private属性
    public int getN4(){
        return n4;
    }

    //四个方法,访问修饰符对应四个属性
    public void test100(){
        System.out.println("test100");
    }
    protected void test200(){
        System.out.println("test200");
    }
    void test300(){
        System.out.println("test300");
    }
    private void test400(){
        System.out.println("test400");
    }
    //父类提供一个public方法,子类可以访问父类的private方法
    public void callTest400(){
        test400();
    }

}
package com.hspedu.extend_;

public class Sub extends Base{//子类
    public Sub(String name, int age){
        //1.调用父类的无参构造器,两种方式:一是super(); 二是什么都不写
        //super();
        //2.调用父类Base(String name)的构造器
        //super("smith");

        //3.调用父类Base(String name, int age)的构造器
        super("smith",25);
        System.out.println("子类的(String name, int age)构造器被调用....");
    }
    public Sub() {
        //super();//隐藏的,创建子类对象的时候会默认调用父类的无参构造器
        super("smith",20);//当父类的无参构造器被覆盖时,用super指定调用父类的构造器
        System.out.println("子类Sub()构造器被调用....");
    }
    //当创建子类对象时, 不管使用子类的哪个构造器, 默认情况下总会去调用父类的无参构造器
    public Sub(String name){
        super("smith",20);
        System.out.println("子类Sub(String name)构造器被调用....");
    }
    public void sayOk(){
        //除了private属性和方法之外都可以访问
        System.out.println(n1 + " " + n2 + " " + n3);
        test100();
        test200();
        test300();
        //test400();
        System.out.println("n4= " + getN4());
        callTest400();//中转
    }

}
package com.hspedu.extend_;

public class ExtendsDetail {
    public static void main(String[] args) {
        //细节说明
//        Sub sub = new Sub();
//        //sub.sayOk();
//        System.out.println("=========第二个对象==========");
//        Sub sub2 = new Sub("jack");
        System.out.println("=========第三个对象==========");
        Sub sub3 = new Sub("ada", 46);


    }
}

 
第五条

super 在使用时, 必须放在构造器第一行(super 只能在构造器中使用)

 第六条

super() 和 this() 都只能放在构造器第一行, 因此这两个方法不能共存在一个构造器

第七条

java 所有类都是 Object 类的子类, Object 是所有类的基类
 

 TopBase类

public class TopBase {//父类是Object类
    public TopBase() {
        System.out.println("构造器TopBase()被调用...");
    }
}

Base类

package com.hspedu.extend_;

public class Base extends TopBase{//父类
    //四个属性,四个访问修饰符
    public int n1 = 100;
    public final int n5 = 500;
    protected int n2 = 200;
    int n3 = 300;
    private int n4 = 400;


    //默认的无参构造器
    public Base() {
        System.out.println("父类Base()的构造器被调用....");
    }
    //父类的有参构造器,两个参数
    public Base(String name, int age){
        System.out.println("父类的(String name, int age)构造器被调用....");
    }
    //一个参数的构造器
    public Base(String name){
        System.out.println("父类的(String name)构造器被调用....");
    }

    //父类提供一个public方法,子类可以访问父类的private属性
    public int getN4(){
        return n4;
    }

    //四个方法,访问修饰符对应四个属性
    public void test100(){
        System.out.println("test100");
    }
    protected void test200(){
        System.out.println("test200");
    }
    void test300(){
        System.out.println("test300");
    }
    private void test400(){
        System.out.println("test400");
    }
    //父类提供一个public方法,子类可以访问父类的private方法
    public void callTest400(){
        test400();
    }

}

Sub类

package com.hspedu.extend_;


//ctrl+H查看继承关系
public class Sub extends Base{//子类
    public Sub(String name, int age){
        //1.调用父类的无参构造器,两种方式:一是super(); 二是什么都不写
        //super();
        //2.调用父类Base(String name)的构造器
        //super("smith");

        //3.调用父类Base(String name, int age)的构造器
        super("smith",25);
        //super() 和 this() 都只能放在构造器第一行, 因此这两个方法不能共存在一个构造器
        //this("jack");//调用本类的Sub(String name)构造器
        System.out.println("子类的(String name, int age)构造器被调用....");

    }
    public Sub() {
        //super();//隐藏的,创建子类对象的时候会默认调用父类的无参构造器
        super("smith",20);//当父类的无参构造器被覆盖时,用super指定调用父类的构造器
        System.out.println("子类Sub()构造器被调用....");
    }
    //当创建子类对象时, 不管使用子类的哪个构造器, 默认情况下总会去调用父类的无参构造器
    public Sub(String name){
        super("smith",20);
        System.out.println("子类Sub(String name)构造器被调用....");
    }
    public void sayOk(){
        //除了private属性和方法之外都可以访问
        System.out.println(n1 + " " + n2 + " " + n3);
        test100();
        test200();
        test300();
        //test400();
        System.out.println("n4= " + getN4());
        callTest400();//中转
    }

}
package com.hspedu.extend_;

public class ExtendsDetail {
    public static void main(String[] args) {
        //细节说明
//        Sub sub = new Sub();
//        //sub.sayOk();
//        System.out.println("=========第二个对象==========");
//        Sub sub2 = new Sub("jack");
        System.out.println("=========第三个对象==========");
        Sub sub3 = new Sub("ada", 46);


    }
}

 

第八条

父类构造器的调用不限于直接父类! 将一直往上追溯直到 Object 类(顶级父类)


第九条

子类最多只能继承一个父类(指直接继承), 即 java 中是单继承机制

第十条

不能滥用继承, 子类和父类之间必须满足 is-a 的逻辑关系

六、继承本质

一个继承的代码案例

package com.hspedu.extend_;

/**
 * 讲解继承的本质
 */
public class ExtendsTheory {
    public static void main(String[] args) {
        Son son = new Son();
    }
}
class GrandPa{//爷爷类
    String name = "大头爷爷";
    String hobby = "旅游";
}
class Father extends GrandPa {//父类
    String name = "大头爸爸";
    int age = 39;
   
}
class Son extends Father { //子类
    String name = "大头儿子";
}


1)类加载的顺序

以上代码中创建子类对象,首先在方法区内进行类的加载,加载顺序是Object----->GrandPat----->Fathert----->Son

2)在堆中给对象分配一个地址空间,空间内的属性如下图所示

3)访问时的查找顺序

package com.hspedu.extend_;

/**
 * 讲解继承的本质
 */
public class ExtendsTheory {
    public static void main(String[] args) {
        Son son = new Son();
        //按照查找关系来返回信息
        //(1) 首先看子类是否有该属性
        //(2) 如果子类有这个属性,并且可以访问,则返回信息
        //(3) 如果子类没有这个属性,就看父类有没有这个属性(如果父类有该属性,并且可以访问,就返回信息..)
        //(4) 如果父类没有就按照(3)的规则,继续找上级父类,直到 Object...
        System.out.println(son.name);//大头儿子
        //System.out.println(son.age);//39,不能访问私有属性,但是空间中这个属性依然是存在的
        //通过父类提供的公共方法来访问private属性
        System.out.println(son.getAge());
        System.out.println(son.hobby);//旅游

    }
}
class GrandPa{//爷爷类
    String name = "大头爷爷";
    String hobby = "旅游";
    //Father中的age是private修饰的,不能直接访问,
    // 就算GrandPa中有属性age,也不会跳过Father去访问GrandPa
    int age = 68;
}
class Father extends GrandPa {//父类
    String name = "大头爸爸";
    private int age = 39;
    public int getAge() {
        return age;
    }
}
class Son extends Father { //子类
    String name = "大头儿子";
}

七、练习题

第三题

 Computer类-父类

package com.hspedu.extend_;

public class Computer {
    private String cpu;
    private int memo;
    private int disk;

    public Computer(String cpu, int memo, int disk) {
        this.cpu = cpu;
        this.memo = memo;
        this.disk = disk;
    }

    public String getCpu() {
        return cpu;
    }

    public void setCpu(String cpu) {
        this.cpu = cpu;
    }

    public int getMemo() {
        return memo;
    }

    public void setMemo(int memo) {
        this.memo = memo;
    }

    public int getDisk() {
        return disk;
    }

    public void setDisk(int disk) {
        this.disk = disk;
    }
    public String getDetails(){
        return "CPU:" + cpu + " 内存:" + memo + " 硬盘:" + disk;
    }
}
package com.hspedu.extend_;

public class PC extends Computer{
    private String brand;

    public PC(String cpu, int memo, int disk, String brand) {
        super(cpu, memo, disk);
        this.brand = brand;
    }


    public void printInfo() {
        System.out.print( "PC信息=");
        System.out.println(getDetails() + " 品牌:" + brand);
    }
}
package com.hspedu.extend_;

public class NotePad extends Computer{
    private String color;

    public NotePad(String cpu, int memo, int disk, String color) {
        super(cpu, memo, disk);
        this.color = color;
    }

    public void printInfo() {
        System.out.print( "NotePad信息=");
        System.out.println(getDetails() + " 颜色:" + color);
    }
}
package com.hspedu.extend_;

public class ExtendsExercise03 {
    public static void main(String[] args) {
        PC pc = new PC("AMD", 12, 512, "联想");
        NotePad notePad = new NotePad("Inter", 12, 420, "银灰");
        pc.printInfo();
        notePad.printInfo();
    }
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/354987.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RAY - 小记

文章目录关于 RAYRAY 结构关于 RAY Ray is a unified framework for scaling AI and Python applications. Ray consists of a core distributed runtime and a toolkit of libraries (Ray AIR) for accelerating ML workloads. RAY 是一个简单、通用的分布式计算框架。 RAY 解…

TikTok话题量超30亿,这款承载美好记忆的剪贴簿引发讨论

回忆风剪贴簿在TikTok引起关注小超在浏览超店有数后台时发现,有一款平平无奇的剪贴簿的种草视频爆火,在24h内收获了9.9K点赞,播放量更是突破了100W,直接冲到了【种草视频飙升榜】第六名的位置,并且这个数字目前仍在继续…

利用5G工业网关实现工业数字化的工业互联网解决方案

5G工业网关是一种用于将工业生产环境中的数据连接到工业互联网的解决方案。它可以利用高带宽、高速率、低时延的5G网络连接工业现场的PLC、传感器、工业设备和云端数据中心,从而实现工业数字化。 物通博联工业互联网解决方案 物通博联5G工业网关的使用步骤&#x…

XXL-JOB分布式任务调度框架(二)-策略详解

文章目录1.引言2.任务详解2.1.执行器2.2.基础配置3.路由策略(第一个)-案例4.路由策略(最后一个)-案例5.轮询策略-案例6.随机选取7.轮询选取8.一致性hash9.最不经常使用 (LFU)10.最近最久未使用(LRU)11.故障转移12.忙碌转移7.分片广播任务1.引言 本篇文章…

中外互免签证协定一览表(普通护照与公务普通护照)

普通护照:由公安部出入境管理机构或者公安部委托的县级以上地方人民政府公安机关出入境管理机构以及中华人民共和国驻外使馆、领馆和外交部委托的其他驻外机构签发,主要颁发给出国定居、探亲、访友、继承财产、留学、就业、旅游等因私事出国的中国公民。…

[REDIS]redis的一些配置文件

修改配置文件 vim /etc/redis/redis.conf目录 protected-mode tcp-backlog timeout tcp-keepalive daemonize pidfile loglevel databases 设置密码 maxclients maxmemory maxmemory-policy maxmemory-samples 默认情况下 bind127.0.0.1 只能接受本机的访问请求。在不写的情况…

算法导论【字符串匹配】—朴素算法、Rabin-Karp、有限自动机、KMP

算法导论【字符串匹配】—朴素算法、Rabin Karp、有限自动机、KMP朴素字符串匹配算法Rabin-Karp算法有限自动机KMP算法朴素字符串匹配算法 预处理时间:0匹配时间:O((n-m1)m) Rabin-Karp算法 预处理时间:Θ(m),需要预先算出匹…

Lua脚本执行redis指令报错【java.lang.IllegalStateException】

Lua脚本执行redis指令报错【java.lang.IllegalStateException】 问题出现背景 今天在学习redis时,为了让redis的多条指令(取锁、比锁、释放锁)保障原子性,我通过使用一个lua脚本统一去执行redis的的多条指令。在执行lua脚本时报错…

Python3 File(文件) 方法讲解

open() 方法 Python open() 方法用于打开1个文件,并返回文件对象。 在对文件进行处理过程都需要使用到这个函数,如果这个文件无法被打开,会抛出 OSError。 注意:使用 open() 方法一定要保证关闭文件对象,即调用 clo…

vrrp+mstp+osfp经典部署案例

LSW1和LSW2和LSW3和LSW4上面启用vrrpmstp组网: vlan 10 全走LSW1出再走AR2到外网,vlan 20 全走LSW2出再走AR3到外网 配置注意:mstp实例的根桥在哪,vrrp的主设备就是谁 ar2和ar3上开nat ar2和ar3可以考虑换成两台防火墙来做&…

Java基础 -- List集合

Java基础 -- List集合1. Introduction1.1 好处1.2 常用泛型2. 交集,差集等2.1 自身的方法2.2 1.8jdk stream 新特性2.3 Apache的CollectionUtils工具类(推荐)3. 限定泛型范围4. Awakening1. Introduction 1.1 好处 代码复用,多种…

分布式任务处理:XXL-JOB分布式任务调度框架

文章目录1.业务场景与任务调度2.任务调度的基本实现2.1 多线程方式实现2.2 Timer方式实现2.3 ScheduledExecutor方式实现2.4 第三方Quartz方式实现3.分布式任务调度4.XXL-JOB介绍5.搭建XXL-JOB —— 调度中心5.1 下载与查看XXL-JOB5.2 创建数据库表5.3 修改默认的配置信息5.4 启…

斐波那契数列(递归+迭代)

目录什么是斐波那契数列递归写法使用递归写法的缺点迭代写法(效率高)什么是斐波那契数列 斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多斐波那契(Leonardo Fibonacci)以兔子繁殖为例…

Redis:数据结构

简单动态字符串SDS Redis没有直接使用C语言传统的字符串表示(以空字符结尾的字符数组,以下简称C字符串),而是自己构 建了一种名为简单动态字符串(simple dynamic string, SDS)的抽象类型,并将SDS用作Redis的默认字符 串表示。 SDS 的实现…

aws lambda rust的sdk和自定义运行时

rust的aws sdk 参考资料 https://docs.aws.amazon.com/sdk-for-rust/latest/dg/getting-started.htmlhttps://awslabs.github.io/aws-sdk-rust/https://github.com/awslabs/aws-sdk-rusthttps://github.com/awsdocs/aws-doc-sdk-examples/tree/main/rust_dev_preview rus sd…

XlsReadWriteII EXCEL Cell Font 单元字体设置

XlsReadWriteII EXCEL Cell Font 单元字体设置 通过XLSReadWriteII5在写EXCEL时,由于XLSReadWriteII5中使用的是个性化的TFont,因而通过参数带入TFont,不能完整地将TFont带入Cell的Font,问题解决如下: 一、问题说明 1、…

Python学习-----模块2.0(常用模块之时间模块-->time)

目录 前言: time简介 导入模块 1.时间戳 2.时间元组 (1)把时间戳转换为元组形式 (2)元组转换为时间戳输出 (3)把元组转换为格式化时间 (4)把时间戳转换为格式化时间…

【深度学习】模型评估

上一章——多分类问题和多标签分类问题 文章目录算法诊断模型评估交叉验证测试算法诊断 如果你为问题拟合了一个假设函数,我们应当如何判断假设函数是否适当拟合了?我们可以通过观察代价函数的图像,当代价函数达到最低点的时候,此…

手机/移动端的UI框架-Vant和NutUI

下面推荐2款手机/移动端的UI框架。 其实还有很多的框架,各个大厂都有UI框架。目前,找来找去,只有腾讯的移动端是setup语法写的TDesign,其他大厂,虽然都是VUE3写的,但是都还未改成setup的语法,而…

张晨光-JAVA零基础保姆式JDBC技术教程

JDBC文档 JDBC概述 JDBC概述 Java DataBase Connectivity Java 数据库连接技术 JDBC的作用 通过Java语言操作数据库,操作表中的数据 SUN公司为**了简化、**统一对数据库的操作,定义了一套Java操作数据库的规范,称之为JDBC JDBC的本质 是官方…