java学习计划——day05(继承,多态)

继承

  1. 认识继承
    继承是指,如果有两个类,有很多的重复的代码,那么就可以把重复的写到A上面,然后B继承A,这样B就不需要再写重复代码了。

在这里插入图片描述

  1. 权限修饰符
    一般来说,成员变量都是private修饰,方法都是public修饰,其他两个很少用到。
    缺省就是什么都没有
    在这里插入图片描述

  2. 继承的特点
    1.单继承:一个类只能继承一个直接父类
    2.多层继承:也可以有爷爷类
    3.祖宗类:所有类都是object类的子类
    4.就近原则:优先访问自己类的,自己类没有的才访问父类

在这里插入图片描述

例如这个代码,因为就近原则,第一个输出的name就是show的name;第二个用了this.name是因为成员变量和局部变量相同了,所以加了this;第三个super的用法是指定访问父类的方法或变量

在这里插入图片描述
小结

在这里插入图片描述

  1. 方法重写
    方法重写就是子类跟父类有相似的功能,但是又有细小的区别,那就在子类里重写写一个同名的方法,把父类的覆盖掉。
    注意,再重写的方法上面最好加上@overried,作为方法重写的注解。

小结

在这里插入图片描述

访问权限就是上面的修饰符权限

常见的应用场景是:因为所有的类都是object的子类,当一个类想要直接输出对象数据时,就需要修该object类 的方法
在这里插入图片描述
可以直接右键自动生成
这样,在输出对象的时候,就会输出对象的数据,而不是对象的地址
在这里插入图片描述

  1. 子类构造器的特点
    子类的所有构造器,都会先调用父类的构造器,再执行自己

在这里插入图片描述

new的时候就会访问Zi的无参构造器,但是Zi就会先访问Fu的构造器,再访问自己的。

package com.itheima.extends6constructor;

public class Test {
    public static void main(String[] args) {
        Zi zi = new Zi();
        //认识子类构造器的特点,在看应用场景
        //子类构造器必须先调用父类构造器,再执行自己构造器
        //为什么一定要先super()调用父类构造器呢,是因为赋值的时候,子类里实际上并没有父类属性,所以需要先调用父类构造器,把值赋给父类的公共元素,再把子类单独有的进行赋值
    }
}

class  Zi extends Fu{
    public Zi(){
        //super();//默认存在的写不写都有,作用是调用父类的无参构造器
        //super(66);//指定调用父类有参构造器
        System.out.println("子类无参构造器构造器执行了");
    }
}



class Fu{
    public Fu(){
        System.out.println("父类无参构造器构造器执行了");
    }
    public Fu(int a){
        System.out.println("父类有参构造器构造器执行了");
    }
}

super的作用如图,子类里独有的属性,可以直接赋值,父类的属性,就通过super调用父类的有参构造器进行赋值。

在这里插入图片描述

小结
在这里插入图片描述
6.构造器用this调用兄弟构造器
指的是假设有两个有参构造器,一个接收1,2,3,一个接收1,2,3,4;其中1,2,3都是重复的,那么就可以用this直接调用下面的,进行赋值,代码如下演示:

package com.itheima.extends6constructor;

public class Test2 {
    public static void main(String[] args) {
        //理解this()调用兄弟构造器
        //创建对象,存储一个学生数据
        Student s1 = new Student("小王", 18, '男');
        System.out.println(s1);
        System.out.println("==================");
        Student s2 = new Student("小秦", 22, '男');
        System.out.println(s2);
    }
}

这是两个不同的对象
然后在类里面存储数据

package com.itheima.extends6constructor;

public class Student {
    private String name;
    private int age;
    private char sex;
    private String schoolName;

    public Student() {
    }
    public Student(String name, int age, char sex) {
//        this.name = name;
//        this.age = age;
//        this.sex = sex;
//        this.schoolName = "传智播客";
        //this调用兄弟构造器
        //注意事项:super()、this()必须写到构造器的第一行,且两者不能同时出现
        this(name,age,sex,"传智播客");//这一行代码跟上面四行代码等价
    }

    public Student(String name, int age, char sex, String schoolName) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.schoolName = schoolName;
    }

模板实际有四个数据,而我只输入了三个,应该调用第一个构造器,但是第一个构造器跟第二个构造器又差不多,所有直接把第一个构造器 用this来调用下一个进行了,节省代码;
且this和super都要写到第一排,并且不能同时出现(因为this默认有一个super了)

小结
在这里插入图片描述

多态

  1. 认识多态
    多态指的是:父类引用指向子类对象,然后调用方法时,会根据实际对象去执行对应的方法。

比如

class Animal {
    public void makeSound() {
        System.out.println("动物叫");
    }
}

class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("汪汪汪");
    }
}

class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("喵喵喵");
    }
}

父类都是动物叫,但是不同的动物叫声是不同的
使用多态

public class Test {
    public static void main(String[] args) {
        Animal a1 = new Dog();  // 父类引用指向子类对象
        Animal a2 = new Cat();

        a1.makeSound(); // 输出:汪汪汪
        a2.makeSound(); // 输出:喵喵喵
    }
}

用父类的应用数据指向子类对象,用来区分不同的动物叫,然后输出不同的数据。
对象多态就是上面的解释;
行为多态是指,执行同样的方法,会因为对象多态,而执行相应的子类重写的方法。

注意编译看左边,运行看右边:编译的时候也许不会报错,但是运行的时候可能报错:比如animal有makesound,但是某个子类没有makesound,那么编译的时候不会报错,但是执行的时候会因为缺失方法而报错

在这里插入图片描述

  1. 多态的好处
    多态的好处1:可以解耦合,可以在不修改大量代码的情况下,随意更换子对象
    多态的好处2:父类类型的变量作为参数,可以直接接收一个子类对象,自动识别
package com.itheima.polymorphsm2;

public class Test {
    public static void main(String[] args) {
        //认识多态的代码
        //多态的好处1:右边对象是解耦合的
        Animal a1 = new Tortoise();
        a1.run();
        //多态好处2:父类类型的变量作为参数,可以直接接收一个子类对象
        Wolf w = new Wolf();
        go(w);




    }
    //宠物游戏:所有动物都可以送给这个方法开始跑步
    public static void go(Wolf w){//这里只能接收Wolf类型的参数,但是改成Animal的话,就可以接收所有数据类型了
        System.out.println("开始");
        w.run();


    }



}

多态的问题:多态下不能使用子类的独有功能,只能使用跟父类同名的重写的方法

  1. 多态下的类型转化
    在这里插入图片描述

强制类型转换,比如animal类型的对象想要执行子类的方法,直接使用肯定会报错,那就将animal转换为子类对象的类型,就可以使用子类独有的功能了

        Tortoise t1 = (Tortoise) a1;
        t1.run();

还有一个问题
在这里插入图片描述
也就是说像上一段代码,a1本来就是披着animal外皮的tor,真实类型就是tor,与强转后的类型是相同的,所以不会报错,但是要是不同的话就会报错

所以需要先判断
在这里插入图片描述
代码比如

   if (a1 instanceof Wolf){
            Wolf w2 = (Wolf) a1;
            w2.run();
        }else if (a1 instanceof Tortoise){
            Tortoise t2 = (Tortoise) a1;
            t2.run();
        }

ins相当于一个等号,如果相等,就直接抢强制转换,否则就转换成另一个对象,反正一共就两个

小结
在这里插入图片描述

实际案例

在这里插入图片描述
代码如下:
测试类:

package com.itheima.demo;

import java.util.Scanner;

public class Test {
    public static void main(String[] args) {
        //加油站支付小程序
        //1.创建卡片类,以便创建金卡或者银卡对象,封装车主的数据
        //2.定义一个卡片:card父类,定义金卡和银卡的共同属性和方法
        //3.创建一个金卡对象,继承card类,金卡需要重写消费方法(8折优惠)
        GoldCard gc = new GoldCard("川54474", "小秦","123456789",5000 );
        pay(gc);
        //4.创建一个银卡对象,继承card类,银卡需要重写消费方法(9折优惠)
        SIlverCard sc = new SIlverCard("川456474", "小川","123456789",5000 );
        pay(sc);
        //5.创建一个金卡对象,交给一个独立业务(支付机):存款、消费
        //6.创建一个银卡对象,交给一个独立业务(支付机):存款、消费

    }

    //支付机:用一个方法来刷卡:可能接收金卡,也可能接收银卡
    public static void pay(Card c){
        System.out.println("请刷卡,请您输入当前消费的金额:");
        Scanner sc = new Scanner(System.in);
        double money = sc.nextDouble();

        c.consume(money);


    }
}

这里是创建了两张不同的卡,然后数据赋值,下面再输入消费多少进行计算,这里方法的Card c用到了对象多态,自动识别金卡银卡

卡片模板:

package com.itheima.demo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;


@Data//lombok可以实现为类自动添加getter和setter方法,无参构造器、toString方法
@NoArgsConstructor//添加一个无参构造器
@AllArgsConstructor//添加一个所有参数的有参构造器
public class Card {
    private String cardId;//车牌号
    private String name;
    private String phone;
    private double money;//余额

    //预存金额
    public void deposit (double money){
        this.money += money;
    }


    //消费金额
    public void consume (double money){
        this.money -= money;
    }
}

卡片模板还包含了两个公共的方法,存钱不管金卡银卡都一样,而消费的计算是不一样的,所以需要重写方法,方法多态。

金卡:

package com.itheima.demo;

public class GoldCard extends Card{
    public GoldCard(String cardId, String name, String phone, double money) {
        super(cardId,name,phone,money);
    }

    @Override
    public void consume(double money) {
        System.out.println("您当前金卡消费:"+money);
        System.out.println("优惠后的价格:"+money*0.8);
        if (getMoney()<money*0.8){
            System.out.println("您的余额不足,请充值");
            return;//干掉方法,直接返回
        }

        //更新金卡的账户余额
        setMoney(getMoney()-money*0.8);
        //判断消费大于200,调用一个独有功能,打印洗车票
        if(money*0.8>200){
            printTicket();
        }

    }
    public void printTicket(){
        System.out.println("恭喜您,获得一张洗车票");
    }
}

首先金卡接收数据,然后用super将数据传给模板,然后将double money传给方法输出消费的金额,这里需要进行一个判断,getMoney就是余额,然后再更新余额

银卡:

package com.itheima.demo;

public class SIlverCard extends Card{
    public SIlverCard(String cardId, String name, String phone, double money) {
        super(cardId,name,phone,money);
    }

    @Override
    public void consume(double money) {
        System.out.println("您当前银卡消费:" + money);
        System.out.println("优惠后的价格:" + money * 0.9);
        if (getMoney()<money*0.9){
            System.out.println("您的余额不足,请充值");
            return;//干掉方法,直接返回
        }
        //更新银卡的账户余额
        setMoney(getMoney() - money * 0.9);
    }
}

跟金卡同理

对象多态是“一个引用能指向多种对象”, 方法多态是“一个方法名在不同对象中有不同行为”。 它们共同构成了 Java 中多态的核心能力。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值