java的继承(extends)

一、为什么需要继承

我们编写了两个类,一个是Pupil类(小学生),还有一个是 Graduate(大学毕业生),发现两个类的属性和方法 有很多是相同的,于是便引出了  继承 可以减轻代码的冗余,提升代码的复用性

把多个类共有的方法提取到父类中去,多个类继承父类,可以直接使用父类中的方法

个人理解 类就是模板,父类就是模板的模板

二、继承基本介绍

当多个类存在相同的属性[变量]和方法时,可以从这些类中抽象出 父类,在父类中定义这些相同的属性和方法,只需要通过  extends 来  声明继承父类即可

继承示意图

三、继承的基本语法

class 子类 extends 父类{

}

1、子类会自动拥有父类定义的属性和方法

2、父类又叫  超类、 基类、

3、子类又叫派生类

四、快速入门案例

父类  Student  共有属性方法

package com.lmdedu.extend_.improve;
//父类,是Pupil和Graduate的父类
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);
}
}

Pupil 和 Graduate  写特有属性和方法   并继承  父类Student的   属性方法

package com.lmdedu.extend_.improve;
//extends Student继承父类Student
public class Pupil extends Student {
    //写独特属性和方法
    public void testing(){
        System.out.println("小学生" + name + "正在考小学数学..");
    }
}
package com.lmdedu.extend_.improve;
//extends Student继承父类Student
public class Graduate extends Student{
    public void testing(){
        System.out.println("大学生" + name + "正在考大学数学..");
    }
}

五、继承的细节和注意事项

1、子类 继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问,但是私有属性不能在子类 直接访问,要通过父类提供的公共的方法去访问

父类 Base

package com.lmdedu.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的方法  获取私有的 属性
    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");
    }

    //为了调用私有化 方法 test400,提供一个public方法
    public void callTest400(){
        test400();
    }
}

子类  Sub 

package com.lmdedu.extend_;

public class Sub extends Base{//子类Sub继承父类  Base
    public Sub(){//无参构造器
        System.out.println("Sub().....");
    }

    public void sayOk(){
        //我们发现父类的  非private属性和方法  均可以调用
        //属性
        System.out.println(n1);
        System.out.println(n2);
        System.out.println(n3);
        //方法
        test100();
        test200();
        test300();

        //但是私有属性不能在子类 直接访问,要通过父类提供的公共的方法去访问
        System.out.println("n4 =" + getN4());
        callTest400();


    }
}

main主函数

package com.lmdedu.extend_;

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

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

父类构造器

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

子类构造器

    public Sub(){//无参构造器
        System.out.println("Sub().....");
    }

可以看出  base()...先输出,说明  先进行  父类构造器的初始化,再完成子类构造器的初始化

 

3、当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器

     若父类没有提供无参构造器,必须在子类的构造器中使用  super  去指定使用   父类的哪个构造       器完成父类的初始化,否则编译不通过

父类中未提供无参构造器 ,在子类的构造器中使用super进行指定父类的构造器

子类构造器 如下

    public Sub(){//无参构造器
        //默认调用父类的无参构造器,当父类没有无参构造器时,进行指定
        super("lmd",20);
        System.out.println("Sub().....");
    }

4、若希望指定调用 父类的 某个构造器  需要显式的调用一下   super(参数列表);

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

6、super() 和 this()  都只能放在构造器的第一行,因此不能共存在 一个构造器中(this()是在构造器中调用构造器)

7、java所有的类都是Object的子类(快捷键ctrl + h可以看到所有类的继承关系)

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

让Base继承 TopBase 

TopBase 构造器

    public TopBase(){
        System.out.println("TopBase()构造器被调用");
    }

所以会输出

9、子类 最多只能 直接继承 一个父类,java中是单继承机制

     思考如何 让A类 继承B类和 C类  

     可以让A继承B,B继承C

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

Person is a Music?

Person  Music

Music extends Person//不合理

Animal

Cat extends Animal //合理

六、继承本质详解

下面将通过一个案例分析,当子类继承父类,创建子类对象时,内存中到底发生了什么

结论:当子类对象创建好后,建立 查找的关系

package com.lmdedu.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 = "大头儿子";
}

分析创建子类对象时,内存中到底发生了什么

Son son = new Son();

1、先加载Object类信息,再加载Grandpa类,再加载父类Father,再加载Son类信息

2、在堆中分配一个地址空间  给 对象son

3、地址空间中 有哪些属性

4、将内存空间地址 传给 对象son

属性的访问规则

public class ExtendsTheory {
    public static void main(String[] args) {
        Son son = new Son();//内存的布局
        //看看会输出 哪个 name,
        //按照查找规则返回数据
        //1)首先看子类是否有该属性,
        //2)若子类有这个属性,并且可以访问,则返回信息
        //3)若子类没有这个属性,就看父类有没有这个属性(若父类有这个属性,并且可以访问,则返回信息)
        //4)若父类没有这个属性,按照3)的规则,继续向上找
        System.out.println(son.name);//输出 子类的name属性 大头儿子
        System.out.println(son.age);//输出 父类的age属性 39
        System.out.println(son.hobby);//输出 爷爷类的 hobby属性 旅游
    }
}

思考若将 Father类中的 age属性改为private,则在对象son的存储空间中,是否还有age这个属性?

private int age = 39;

答案是  仍然有  ,只需让 Father 类提供一个公有的访问方法  就能用

思考 若在 Grandpa类中 添加 public age属性,然后将Father类中的  age属性 改为private,直接访问age时是否会跳过  Father类的private age属性,访问Grandpa类中 的 public age属性?

答案是  不会,  只要在查找过程中 ,被挡住了 不会跳过去 向上找

七、课堂练习

注意:有this 就没有super

输出答案

a

b name

b

输出

我是A类

name+"我是B类的有参构造"

”我是C类的有参构造“

”我是C类的无参构造“

package com.lmdedu.extend_;
//测试类
class Test{
    //主方法
    public static void main(String[] args) {
        Pc pc = new Pc("i9","16G","1T","惠普");
        System.out.println(pc.getPcDetail());

        NotePad notePad = new NotePad("i9","16G","1T","black");
        System.out.println(notePad.getNotePadDetail());


    }
}
//父类Computer
class Computer{
    private String cpu;
    private String memory;
    private String hardDisk;

    public Computer(String cpu, String memory, String hardDisk) {
        this.cpu = cpu;
        this.memory = memory;
        this.hardDisk = hardDisk;
    }

    public String getCpu() {
        return cpu;
    }

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

    public String getMemory() {
        return memory;
    }

    public void setMemory(String memory) {
        this.memory = memory;
    }

    public String getHardDisk() {
        return hardDisk;
    }

    public void setHardDisk(String hardDisk) {
        this.hardDisk = hardDisk;
    }

    public String getDetail(){
        return "cpu为" + cpu +"内存为" + memory + "硬盘为" + hardDisk;
    }
}
//子类Pc
class Pc extends Computer{
    String brand;
    //这里也体现出:继承设计的基本思想
    //父类的构造器完成 父类属性初始化
    //子类的构造器完成 子类属性初始化
    public Pc(String cpu, String memory, String hardDisk, String brand) {
        super(cpu, memory, hardDisk);
        this.brand = brand;
    }

    public String getPcDetail(){
        return getDetail() + "品牌为" + brand;
    }
}

class NotePad extends Computer{
    String color;


    public NotePad(String cpu, String memory, String hardDisk, String color) {
        super(cpu, memory, hardDisk);
        this.color = color;
    }

    //打印信息
    public String getNotePadDetail(){
        return getDetail() + "颜色为" + color;
    }
}


  • 26
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在C#项目中集成ChatGPT可以通过引用openAI SDK并调用openAI API来实现。以下是一个示例代码: ```csharp using OpenAI_API; using OpenAI_API.Model; // 创建API客户端 var client = new OpenAIClient("YOUR_API_KEY"); // 调用API var response = client.Completions.CreateCompletion( new CompletionRequest { Model = "davinci", Prompt = "Hello, my name is", MaxTokens = 5 } ); // 获取API响应 var result = response.Choices\[0\].Text; ``` 这段代码演示了如何使用C#调用openAI API来生成ChatGPT的回复。首先,你需要引用openAI SDK并创建一个API客户端。然后,你可以使用`CreateCompletion`方法来发送API请求,并传递所需的参数,如模型名称、提示信息和最大令牌数。最后,你可以从API响应中获取生成的回复。 请注意,你需要将`YOUR_API_KEY`替换为你自己的openAI API密钥。此外,你可能还需要根据你的具体需求调整其他参数,如模型名称和最大令牌数。 #### 引用[.reference_title] - *1* [C#/.Net开发chatGPT、openAI的简单步骤](https://blog.csdn.net/sD7O95O/article/details/130939141)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [0基础快速集成ChatGPT!请收藏好这份保姆级入门指南!](https://blog.csdn.net/weixin_51484460/article/details/130527750)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值