2022-07-21第八组wly Java面向对象(4)---继承

发布于:2023-02-17 ⋅ 阅读:(432) ⋅ 点赞:(0)

今日重点:

目录

一、Java面向对象的特点之一:继承

1.继承的实现

(1)概念: 

(3)继承的注意事项

 (4)继承能干什么

 2、继承中成员访问的特点

(1)构造方法访问特点

(2)变量和成员方法的访问特点

(3)super和this关键字的区别

3、方法重写 

(1)定义:

(2) 方法的重写的规则

(3)应用场景

(4)方法重写和方法重载的区别:(面试题)

(5)方法重写的注意事项

二、课上实例

Biology类的代码

Animal类的代码

Person类的代码

Cat类的代码

主类的代码

调用方法重写的代码

三、实际案例

主类Demo

银行卡类Card

借记卡类DebitCard

信用卡类CreditCard

一、Java面向对象的特点之一:继承

类与类之间的关系:
 * 1.属性关系
 * 2.参数关系
 * 3.继承关系

1.继承的实现

(1)概念: 

继承是面向对象三大特性之一,可以使得子类具有父类的属性和方法,还可以在子类中重新定义以及追加属性和方法,继承通过extends实现。在Java中,继承是单继承,一个子类只能有一个直接父类,但是可以有多个间接父类,extends后面只能写一个类。

父类(超类superclass)

子类(基类 subclass)​​​​​​


(2)实现格式

  • 格式:class 子类 extends 父类 { }
  • 举例:class Cat extends Animal { }

(3)继承的注意事项

1.子类不是无限继承父类中的内容,它只能继承父类中非私有(非private修饰)的代码,也不能继承构造方法,也不能继承不同包中,默认修饰的内容。
2.只能继承父类中非私有(非private修饰)的代码:private修饰的内容是私有的,只能在本类中使用。(话糙理不糙:你爸爸的闺女 不是你的闺女 你是无法继承这关系)

3.不能继承构造方法:构造方法是用来初始化对象(对象创建),它是给父类创建对象用的。(话糙理不糙:生你爸爸的人 不能生你)

访问权限修饰符:
 * 1.public
 * 2.protected 受保护的,不同包的子类可以访问
 * 3.default  默认的
 * 4.private

 (4)继承能干什么

 * 1.子类可以继承父类的属性
 * 2.子类·可以继承了父类的方法
 * 3.创建子类对象时(创建对象的过程就是实例化的过程),执行了父类的构造器,父类先被实例化,再去实例化子类。
 * 4.当一个类被实例化时,一定会先实例化它的间接父类,再直接父类,再实例化它自己(先有爷爷再有爸爸再有自己)
 *注意:子类的构造器可以有多个,但是必须和父类的构造器形式上统一。

 2、继承中成员访问的特点

(1)构造方法访问特点

子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化之前,一定要先完成父类数据的初始化,原因在于,每一个子类构造方法的第一条语句默认都是:super()
注意:子类中所有的构造方法默认都会访问父类中无参的构造方法,如果父类中只有带参构造方法,我们又需要使用无参构造方法时,一般自己给出无参构造方法

(2)变量和成员方法的访问特点

1.变量

①子类局部范围找
②子类成员范围找
③父类成员范围找
④如果都没有就报错(不考虑父亲的父亲…)

2.成员方法

①子类成员范围找

②父类成员范围找

③如果都没有就报错(不考虑父亲的父亲…)

(3)super和this关键字的区别

1.定义:
this:代表本类对象的引用,代表当前对象的引用,谁来调用我,我就代表谁
super:代表父类存储空间的标识,代表当前对象父类的引用


2.使用区别:
①调用成员变量
this.成员变量 调用本类的成员变量,也可以调用父类的成员变量
super.成员变量 调用父类的成员变量
②调用构造方法
this(…) 调用本类的构造方法
super(…) 调用父类的构造方法
③调用成员方法
this.成员方法 调用本类的成员方法,也可以调用父类的方法
super.成员方法 调用父类的成员方法

 以上参考的文章博客链接为:https://blog.csdn.net/zyl1112/article/details/120830702?utm_source=app&app_version=5.2.1&code=app_1562916241&uLinkId=usr1mkqgl919blen

面试题:this和super的区别?
 *  在子类中当使用super调用父类的构造器时,super(age)必须是第一句话
 *  在当前类中使用this调用本类的构造器时,this(name)必须是第一句话
 *  在构造器中,如果需要使用super或this调用其他(子类或者父类)构造器,只能二选一,而且还必须是第一句话
 *  super指向的父类,不代表任何对象。
 *  this指向的本类,代表当前类的对象,方法的调用者。

3、方法重写 

(1)定义:

子类出现了和父类中一模一样的方法声明(方法名一样,参数列表也必须一样)

①子类可以重写父类的方法
②方法的重写,我们可以利用到父类中方法已经运算过的结果,在结果的基础上进行扩展
③方法的重写,体现的就是继承的核心,就是为了扩展父类的功能。
④开发中,如果要重写,基本就是一模一样,我们只变方法体

⑤重写的方法的返回值可以是被重写方法的返回值的子类。
(2) 方法的重写的规则

---前提,继承与被继承的关系(父类与子类):
①.访问权限:重写的方法的权限不能低于被重写的方法。开发中一般都是等于。
②返回值类型:重写的方法的返回值可以和被重写的方法不同,但是必须是被重写方法的返回值的子类。开发中,一般就是一样。
③.方法名:必须相同
④.参数列表:参数类型,参数个数必须相同。
⑤抛出异常:重写的方法不能抛出比被重写的方法更大的异常
 

(3)应用场景

当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法,这样,即沿袭了父类的功能,又定义了子类特有的内容

(4)方法重写和方法重载的区别:(面试题)

方法的重写(Override)和重载(Overload)是java多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载可以理解成多态的具体表现形式。
①方法重载是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同,则称为方法的重载(Overload)。
②方法重写是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法,就称为重写(Override)。
③方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。
 

(5)方法重写的注意事项

私有方法不能被重写(父类私有成员子类是不能继承的)。
子类方法访问权限不能更低(public > 默认 > 私有)。

 以上参考的文章博客链接为:

https://blog.csdn.net/youzixiao/article/details/107141390?utm_source=app&app_version=5.2.1&code=app_1562916241&uLinkId=usr1mkqgl919blen

二、课上实例

我们创建四个类,Biology类,Animal类,Person类,Cat类

Biology类的代码

//Biology类的代码:
package com.jr.morning;

public class Biology {
    protected String name;
    Integer age;//Integer:包装器类型

    public Biology() {
    }

    public Biology(Integer age) {
        this.age = age;
        System.out.println("生物类的构造器...");
    }

    public void breath(){

    }
}

Animal类的代码

//Animal类的代码:
package com.jr.morning;

public class Animal extends Biology{

    public Animal() {//无参构造
    }

    public Animal(Integer age) {
        super(age);//super:代表调用父类的结构(属性、方法、构造器)
        System.out.println("动物类的构造器...");
    }
    public Animal(Integer age,String name) {
        super(age);//在子类中当使用super调用父类的构造器时,super(age)必须是第一句话
        //this(age);//在构造器中,如果需要使用super或this调用其他(子类或者父类)构造器,只能二选一,而且还必须是在第一句话
        this.name = name;
       //this(name);
    }

    public void eat(){
        // 调用父类的属性
        age = 20;//super.age=20;
        // 调用父类的方法
        breath();//super.breath();
        // 调用当前类的属性
        name = "z";//this.name="z";
        //this和super都可以省略掉,代表先在本类找,没找到就是去父类找



    }

    public void drank(String water) {
        System.out.println("动物在喝" + water);
    }

    public String show() {
        return "我们很优秀";
    }

    public Biology info(Biology biology) {

        return null;
    }
}

Person类的代码

//Person类的代码:
package com.jr.morning;

public class Person extends Animal {
    public Person() {
    }

    public Person(Integer age) {
        super(age);
        System.out.println("人类的构造器...");
    }

    public void drank(String water){
        System.out.println("人在喝" + water);
        System.out.println("喝完了" + water + "再来一杯!");
    }

     public String show(){
        // 返回的是我们很优秀,我们很直溜
        return super.show() + "我们很直溜";
    }

    public Animal info(Biology animal){

        return null;
    }


}

Cat类的代码

//Cat类代码:
package com.jr.morning;

public class Cat extends Animal{
    public Cat(Integer age) {
        super(age);
    }
}

主类的代码

package com.jr.morning;
public class Ch01 {
    public static void main(String[] args) {
           //生物类的对象
        Biology biology = new Biology();
        biology.age = 20;//调属性
        biology.breath();//调方法

        //动物类的对象
        Animal animal = new Animal(30);
        animal.age = 30;//当Animal类中什么都没有写的时候,这里也可以写age,breath
        animal.breath();//因为这是从Biology父类继承过来的属性和方法
       //人类的对象
        Person person = new Person();
        person.age = 35;//继承间接分类的age属性
        person.name = "张三";//继承直接父类的name属性
        person.eat();//继承直接分类的eat方法
        person.breath();//继承间接父类的breath方法
    }
}


调用方法重写的代码

package com.jr.morning;

public class Ch02 {
    public static void main(String[] args) {
        Person person = new Person();//得到类的对象
        person.drank("江小白");//调用本类Person类的drank方法,不能调用Animal类的方法
    }
}

三、实际案例

----需求 :

1.有一个银行卡类,有账号和密码,余额,有存款和取款的方法。
2.创建一个借记卡类,继承于银行卡,转账额度。存款和取款的方法,取款的时候,如果超过了20000,则提示需要去柜台拿身份真办理! ! !
4.创建一个信用卡类,继承于银行卡,信用额度。
5.有存款和取款的方法。
取款:如果余额大于0,则从余额中扣,如果余额小于等于0, 则会走信用额度
余额: 100, 信用额度: 50000, 1000

我们创建四个类:主类Demo,银行卡类Card,借记卡类DebitCard,信用卡类CreditCard

这里有两个版本,这个案例是上课针对本节课知识点做的针对性练习,易理解所以就存在一些bug,进阶版更简洁一些,用到了链式编程(链式处理)。

链式;

        1.编程性强;

        2.可读性强;

        3.代码更简洁;

        4.对程序员的业务能力要求高;

        5.不太利于代码调试;

链式编程可以使得代码可读性高,链式编程的原理就是返回一个this对象,就是返回本身,达到链式效果。看到this关键字,我们首先应该想到1.它代表当前类对象2.代表当前方法的调用者。在链式编程中,this关键字起到的作用就是当前方法的调用者。
 

主类Demo

package com.jr.morning.Test1;

public class Demo {
    public static void main(String[] args) {
        /*
        //测试借记卡DebitCard
        DebitCard debitCard=new DebitCard("123456","123456",Double.valueOf(100),Double.valueOf(20000));//得到DebitCard类对象
        Double in=debitCard.in(10000000.0);//存款
        in =debitCard.out(300000.0);//取款
        if (in >=0){
            System.out.println("余额为:"+in);
        }else if(in==-1){
            System.out.println("取款失败,余额不足!");
        }else if (in==-2){
            System.out.println("取款失败,今日取款额度不足!");
        }

         */
        //测试信用卡CreditCard
        CreditCard creditCard=new CreditCard("123456","123456",1000.0,50000.0);
        System.out.println("剩余额度为:"+creditCard.out(2000.0));//取款。结果返回剩余额度
        System.out.println("余额为:"+creditCard.in (3000.0));//存款。结果返回余额


    }
}

进阶版:

public class Demo {
    public static void main(String[] args) {
        DebitCard debitCard = new DebitCard("123456", "123456", 100.0, 2000.0);
        Card card = debitCard.in(2000.0);//存钱,赋值给card
        System.out.println("存款成功:" + card.getCardId() + "的余额为:" + card.getBalance());
        DebitCard d = debitCard.out(1500.0);//存钱,赋值给card
        if (d.getBalance() >= 0) {
            System.out.println("取款成功:" + d.getCardId() + "的余额为:" + d.getBalance());
        } else if (d.getBalance() == -1) {
            System.out.println("余额不足!" );
        } else if (d.getBalance() == -2) {
            System.out.println("取款额度不足!");
        }
    }
}

银行卡类Card

package com.jr.morning.Test1;

import java.util.Date;

//银行卡
public class Card {//父类
    private String cardId;
    private String password;
    private double balance;//余额


    //构造函数
    public Card(String cardId, String password, double balance) {
        this.cardId = cardId;
        this.password = password;
        this.balance = balance;
    }

    public Card() {//养成一个习惯,构造函数之后,每个类还应该构造一个无参构造器
    }

    public Double in(Double money) {//存款
        balance += money;//给balance赋值
        return balance;//返回余额
    }

    public Double out(Double money) {//取款
        balance -= money;
        return balance;
    }

    //构造setter,getter方法
    public String getCardId() {
        return cardId;
    }

    public void setCardId(String cardId) {
        this.cardId = cardId;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }
}

进阶版:

package com.jr.morning.Test;

import java.util.Date;

//银行卡
public class Card {//父类
    private  String cardId;
    private  String password;
    private  double balance;//余额


    //构造函数
    public Card(String cardId, String password, double balance) {
        this.cardId = cardId;
        this.password = password;
        this.balance = balance;
    }

    public Card() {//养成一个习惯,构造函数之后,每个类还应该构造一个无参构造器
    }

    public Card in(Double money){//存款
        balance += money;//给balance赋值
        this.setBalance(balance);
        return this;//返回余额
    }
    public Card out(Double money){//取款
       balance-=money;
       Card card=new Card(cardId,password,balance);//获取Card类的属性
        return card;//返回给Card
    }
    //构造setter,getter方法
    public String getCardId() {
        return cardId;
    }

    public void setCardId(String cardId) {
        this.cardId = cardId;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }
}

借记卡类DebitCard

package com.jr.morning.Test1;

import java.awt.datatransfer.Transferable;
import java.util.Date;

//借记卡
public class DebitCard extends Card {//DebitCard子类继承Card父类
    private Double TransferAmount;//加入一个转账额度的属性

    public DebitCard() {
    }

    public DebitCard(String cardId, String password, double balance, Double TransferAmount) {
        super(cardId, password, balance);//调用父类的构造函数(属性)
        this.TransferAmount = TransferAmount;//传进来的TransferAmount赋值给调用本类的TransferAmount
    }

    public Double out(Double money) {//方法重写---DebitCard中的取款,写取款是因为借记卡里得判断一下余额
        //借记卡的取款,除了要考虑余额是否足够。转账额度问题,超过20000
        if (getBalance() >= money && TransferAmount >= money) {// 不用直接用super直接调用父类Card的属性了,因为private  double balance;中有private代表属性私有化了,不能调用
            //但是可以用get方法调用余额Balance---getBalance
            //getBalance()>=money&&TransferAmount>=money代表余额要足够,额度要足够,可以直接调用父类方法
            return super.out(money);


        } else if (getBalance() < money) {
            return Double.valueOf(-1);//自己定义的规则,如果方法的返回值等于-1,说明余额不足
        } else if (TransferAmount < money) {
            return Double.valueOf(-2);//自己定义的规则,如果方法的返回值等于-2,说明额度不够
        }
        return Double.valueOf(-3);//自己定义的规则,如果方法的返回值等于-3,说明是其他情况
    }
}

进阶版:

package com.jr.morning.Test;

import java.awt.datatransfer.Transferable;
import java.util.Date;

//借记卡
public class DebitCard extends Card {//DebitCard子类继承Card父类
    private Double TransferAmount;//加入一个转账额度的属性

    public DebitCard() {
    }

    public DebitCard(String cardId, String password, double balance, Double TransferAmount) {
        super(cardId, password, balance);//调用父类的构造函数(属性)
        this.TransferAmount = TransferAmount;//传进来的TransferAmount赋值给调用本类的TransferAmount
    }

    public DebitCard out(Double money) {//方法重写---DebitCard中的取款,写取款是因为借记卡里得判断一下余额
        //借记卡的取款,除了要考虑余额是否足够。转账额度问题
        //我们需要DebitCard类的对象,那我们就去得到DebitCard类
        DebitCard debitCard=new DebitCard();
        if (getBalance() >= money && TransferAmount >= money) {// 不用直接用super直接调用父类Card的属性了,因为private  double balance;中有private代表属性私有化了,不能调用
            //但是可以用get方法调用余额Balance---getBalance
            //getBalance()>=money&&TransferAmount>=money代表余额要足够,额度要足够,可以直接调用父类方法
            Card card= super.out(money);
            //把父类的属性设置给子类
            debitCard.setCardId(card.getCardId());
            debitCard.setPassword(card.getPassword());
            debitCard.setBalance(card.getBalance());
            //括号里边get方法是获取属性,是父类对象拿它自己的属性给子类
           //括号外边是用子类对象去设置属性(set方法)

            return debitCard;
        } else if (getBalance() < money) {//取款失败
            debitCard.setBalance(Double.valueOf(-1));//Double.valueOf是把-1强制转换成double类型的数据
            return debitCard;//自己定义的规则,如果方法的返回值等于-1,说明余额不足
        } else if (TransferAmount < money) {
            debitCard.setBalance(Double.valueOf(-2));
            return debitCard;//自己定义的规则,如果方法的返回值等于-2,说明额度不够
        }
            return null;//返回空值,说明是其他情况
    }
}

信用卡类CreditCard

package com.jr.morning.Test1;

public class CreditCard extends Card {//CreditCard子类继承Card父类


    private  Double credits;//CreditCard的信用额度属性
    private  Double temp=0.0;//定义一个临时属性

    public CreditCard() {//CreditCard类的无参构造器
    }

    public CreditCard(String cardId, String password, double balance, Double credits) {
        super(cardId, password, balance);
        this.credits = credits;
    }
    public Double in(Double money){//方法重写---CreditCard的存款
        //信用卡的存款,首先要还额度,其次此时存款
        if (temp==0.0){//判断临时的temp里的额度是不是0
            return super.in(money);//如果是0,说明额度是够的,不用先还额度,直接存款就可以
        }

        if (temp>=money){//如果额度欠的钱比存的money还多或正好相等,要先还额度,剩下的钱才是余额
            credits += money;//看额度还差多少
            temp -= money;//欠的额度还剩多少
            return  credits;
        }
        if (temp <money){//如果额度欠的钱比存的money还少,
            credits += temp;//额度满级
            setBalance(money-temp);//获取还额度之后的余额
            temp =0.0;//不欠额度了
            return getBalance();//返回信用卡的余额
        }
        return null;
    }
    public Double out(Double money){//方法重写---CreditCard的取款
        //取款先走余额,再走信用额度
        if(getBalance() >= money){
            return  super.out(money);
        } else if (getBalance() < money && credits < money) {//取款的时候,余额不够,额度也不够
            return Double.valueOf(-1);//就返回-1
        } else if (getBalance() < money && credits > money) {//余额不够,额度够
            double d = money - getBalance();
            credits = credits -d ;//剩余的信用额度
            temp = d;//让temp把剩余额度存起来
            return  credits;//返回信用额度
        }
        return null;
    }
}

进阶版:

package com.jr.morning.Test;
//信用卡
public class CreditCard extends Card {//CreditCard子类继承Card父类


    private  Double credits;//CreditCard的信用额度属性
    private  Double temp=0.0;//定义一个临时属性

    public CreditCard() {//CreditCard类的无参构造器
    }

    public CreditCard(String cardId, String password, double balance, Double credits) {
        super(cardId, password, balance);
        this.credits = credits;
    }
    public CreditCard in(Double money){//方法重写---CreditCard的存款
        //信用卡的存款,首先要还额度,其次此时存款
        if (temp==0.0){//判断临时的temp里的额度是不是0
            return null;//如果是0,说明额度是够的,不用先还额度,直接存款就可以
        }

        if (temp>=money){//如果额度欠的钱比存的money还多或正好相等,要先还额度,剩下的钱才是余额
            credits += money;//看额度还差多少
            temp -= money;//欠的额度还剩多少
            return  null;
        }
        if (temp <money){//如果额度欠的钱比存的money还少,
            credits += temp;//额度满级
            setBalance(money-temp);//获取还额度之后的余额
            temp =0.0;//不欠额度了
            return null;
        }
       return null;
    }
    public CreditCard out(Double money){//方法重写---CreditCard的取款
        //取款先走余额,再走信用额度
        if(getBalance() >= money){
            return  null;
        } else if (getBalance() < money && credits < money) {//取款的时候,余额不够,额度也不够
            return null;
        } else if (getBalance() < money && credits > money) {//余额不够,额度够
            double d = money - getBalance();
            credits = credits -d ;//剩余的信用额度
            temp = d;//让temp把剩余额度存起来
            return null;
        }
        return null;
    }
}

今日总结:

这是学习Java面向对象的第三天,知识点是继承,掌握程度算三颗星吧。写银行卡案例的时候自己还是没能写出来,甚至思路也很少,说明自己对知识点的总体掌握情况不是很理想,我自我反思觉得原因应该是前两天的知识没学好,后面就有点跟不上了。人生如同过韶关,关关难过关关过,继续加油吧。 

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到