java学习笔记day11-继承-抽象类-代码块

Day11

继承
继承概述
  • 继承是面向对象三大特征(封装、继承、多态)之一。可以使得子类具有父类的属性和方法,还可以在子类中重新定义,追加属性和方法。
  • 格式:public class 子类名 extends 父类名{}
  • 范例:public class Zi extends Fu{}
  • Fu:是父类,也被称为基类、超类
  • Zi:是子类,也被称为派生类
继承的特点
  • java只支持单继承,不支持多继承,但支持多层继承。
继承中子类的特点:
  • 子类可以有父类的内容
  • 子类还可以有自己的特有的内容
继承的好处和弊端

继承的好处

  • 提高了代码的复用性(多个类相同的成员可以放到同一个类中)
  • 提高了代码的维护性(如果方法的代码需要修改,修改一处即可)

继承弊端

  • 继承让类与类之间产生了关系,类的耦合性增强了,当父类发生变化时,子类实现也不得不跟着变化,削弱了子类的独立性

什么时候用继承

  • 继承体现的关系:is a
  • 假设法:有两个类A和B,如果他们满足A是B的一种,或者B是A的一种,就说明他们存在继承关系,这个时候就可以考虑使用继承来体现,否则就不能滥用继承
继承中成员变量的访问特点
  • 在子类中访问一个变量 的优先级
    • 子类局部范围找
    • 子类成员范围找
    • 父类成员范围找
    • 如果没有就报错(不考虑父亲的父亲…)
    • **注意:**如果子父类中,出现了重名的成员变量,通过就近原则,会优先使用子类的,如果一定要使用父类的,可以通过super关键字,进行区分。
继承中成员方法访问的特点
  • 通过子类对象访问一个方法
    • 子类成员范围找
    • 父类成员范围找
super

​ super关键字的用法和this关键字的用法相似

  • this:代表本类对象的引用(this关键字指向调用该方法的对象,一般我们是在当前类中使用this关键字,所以我们常说this代表本类对象的引用)
  • super:代表父类存储空间的标识(可以理解为父类对象引用)
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YMOxlsUU-1608126275079)(C:\Users\花花\AppData\Roaming\Typora\typora-user-images\image-20201215111209141.png)]
方法重写
  • 概述:在继承体系中,子类出现了和父类中一模一样的方法声明

  • 应用场景

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

    • 示例:

    • 父类
      public class OldPhone {
          public void call(String name){
              System.out.println("给"+name+"打电话");
          }
          public void speak(){
              System.out.println("说英文");
          }
      }
      
      
      子类
      public class NewPhone extends OldPhone {
          public void speak(){
              super.speak();
              System.out.println("说中文");
          }
      }
      
      测试类
      public class Test {
          public static void main(String[] args) {
              NewPhone newPhone = new NewPhone();
              newPhone.speak();
              newPhone.call("澜");
          }
      }
      
  • 注意:

    • 方法重写:在继承体系中,子类出现了和父类一模一样的方法声明(方法名、参数列表、返回值类型)
    • 方法重载:在同一个类中,方法名相同,参数列表不同,与返回值无关。
方法重写注意事项
  • 父类中私有方法不能被重写
  • 父类静态方法,子类必须通过静态方法进行重写,父类非静态方法,子类也必须通过非静态方法进行重写
    • 注意:静态方法不能被重写,如果子类中,也存在一个方法声明一模一样的方法,可以理解为,子类将父类中同名方法,隐藏了起来,并非是方法重写!
  • 子类重写父类方法时,访问权限必须大于等于父类
  • 权限修饰符
    在这里插入图片描述
继承中构造方法的访问特点

​ 继承中所有的构造方法默认都会访问父类中无参的构造方法

为什么?

  • 子类在初始化的时候,有可能会使用到父类中的数据,如果没有完成初始化,子类将无法使用父类的数据。 子类初始化之前,一定要先完成父类初始化。

怎么初始化?

  • 构造方法的第一条语句默认都是:super()

**注意:**如果我们编写的类,没有手动指定父类,系统也会自动继承Object(Java继承体系中的最顶层父类)

示例:

父类Person.java

package gouzao;

public class Student extends Person{
    private int score;

    public Student(){
        //子类初始化之前,一定要先完成父类数据的初始化
        //子类初始化之前,一定要先访问到父类的构造方法,完成父类数据的初始化
        //系统在每一个构造方法中,默认隐藏一句代码super();
        System.out.println("我是子类的无参构造");
    }

    public Student(int score){
        this.score=score;
        System.out.println("我是子类的带参构造");
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }
}

子类Student.java

package gouzao;

public class Student extends Person{
    private int score;

    public Student(){
        //子类初始化之前,一定要先完成父类数据的初始化
        //子类初始化之前,一定要先访问到父类的构造方法,完成父类数据的初始化
        //系统在每一个构造方法中,默认隐藏一句代码super();
        System.out.println("我是子类的无参构造");
    }

    public Student(int score){
        this.score=score;
        System.out.println("我是子类的带参构造");
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }
}

测试类Test.java

package gouzao;

public class Test {
    public static void main(String[] args) {
        Student stu = new Student();

        Student stu1 = new Student(100);
    }
}

运行结果:
在这里插入图片描述

如果父类中没有空参构造方法,只有带参构造方法,会出错,解决办法:

  • 子类通过super,手动调用父类的带参的构造方法
  • 子类通过this去调用本类的其他构造方法,本类其他构造方法再通过super去手动调用父类的带参构造方法
  • 注意:this()super()必须放在构造方法的第一行有效语句,并且二者不能共存
抽象类
概述
  • 抽象方法:将共性的行为(方法)抽取到父类之后,发现该方法的实现逻辑无法在父类中给出具体明确,该方法就可以定义为抽象方法;
  • 抽象类:如果一个类中存在抽象方法,那么该类就必须声明为抽象类;
作用
  • 抽象类可以作为一些设计模式使用;
  • 抽象类中可以写抽象方法。
定义抽象方法的作用
  • 抽象方法可以强制子类必须重写父类抽象方法;
案例:猫和狗

需求:定义猫类(Cat)和狗类(Dog)

​ 猫类成员方法:eat(猫吃鱼)drink(喝水…)

​ 狗类成员方法:eat(狗吃肉)drink(喝水…)

分析:

  1. 猫类和狗类中存在共性内容,应向上抽取出一个动物类(Animal)
  2. 父类Animal中,无法将eat方法具体实现描述清楚,所以定义为抽象方法
  3. 抽象方法需要存活在抽象类中,将Animal定义为抽象类
  4. 让Cat和Dog分别继承Animal,重写eat方法
  5. 测试类中创建Cat和Dog对象,调用方法测试

Animal类:

package chouxiang;

public abstract class Animal {
    public void drink(){
        System.out.println("喝水");
    }
    public abstract void eat();
}

Cat类:

package chouxiang;

public class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}

Dog类:

package chouxiang;

public class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("狗吃肉");
    }
}

测试类Test:

package chouxiang;

public class Test {
    public static void main(String[] args) {
        Dog d = new Dog();
        d.eat();
        d.drink();
        Cat c = new Cat();
        c.eat();
        c.drink();
    }
}

运行结果:
在这里插入图片描述

  • 抽象方法的定义格式:
    • public abstract 返回值类型 方法名(参数列表);
  • 抽象类的定义格式:
    • public abstract class 类名{}
抽象类的注意事项
  1. 抽象类不能创建对象(不能实例化)
  2. 抽象类中有构造方法
  3. 抽象类的子类
    • 必须要重写父类中所有的抽象方法
    • 可以将自己也变成一个抽象类
  4. 抽象类中的方法
    • 抽象类中可以没有抽象方法,但是有抽象方法的类一定是抽象类
模板设计模式
  • 设计模式是一套反复被使用、多数人只晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。
  • 模板设计模式:把抽象类整体就可以看做成一个模板,模板中不能决定的东西定义成抽象方法,让使用模板的类(继承抽象类的类)去重写抽象方法实现需求;
  • 小结:模板设计模式的优势,模板已经定义了通用结构,使用者只需要关心自己需要实现的功能即可。
final关键字

final修饰的特点

  • 修饰方法:表明该方法是最终方法,不能被重写
  • 修饰变量:表明该变量是常量,不能再次被赋值
    • 基本数据类型变量:其值不能被更改
    • 引用数据类型变量:地址值不能被更改,但可以更改对象的属性值
  • 修饰类:表明该类是最终类,不能被继承

final修饰成员变量,初始化时机

  1. 在创建的时候直接给值
  2. 在构造方法结束之前,完成赋值
代码块
代码块概述与分类

在java中,使用{}括起来的代码块被称为代码块

分类:

  • 局部代码块
    • 位置:方法中定义
    • 作用:限定变量的生命周期,及早释放,提高内存利用率
  • 构造代码块
    • 位置:类中方法外定义
    • 特点:每次构造方法执行时,都会执行该代码块中的代码,并且在构造方法执行前执行
    • 作用:将多个构造方法中相同的代码,抽取到构造代码块中,提高代码的复用性
  • 静态代码块
    • 位置:类中方法外定义
    • 特点:需要通过static关键字修饰,随着类的加载而加载,并且只执行一次
    • 作用:在类加载的时候做一些数据初始化的操作
练习1

​ 我们计划为一个电器销售公司制作一套系统,公司的主要业务是销售一些家用电器,例如:电冰箱、洗衣机等。

  • 冰箱类:

    • 属性:品牌、型号、颜色、售价、门款式、制冷方式
  • 洗衣机类:

    • 属性:品牌、型号、颜色、售价、电机类型、洗涤容量

    请根据上述类的设计,抽取父类“电器类”,并代码实现父类“电器类”、子类“冰箱类”,“洗衣机类”;

父类Dianqi.java

package lian1;

public class Dianqi {
    private String brand;
    private String version;
    private String color;
    private double price;

    public Dianqi() {
    }

    public Dianqi(String brand, String version, String color, double price) {
        this.brand = brand;
        this.version = version;
        this.color = color;
        this.price = price;
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public String getVersion() {
        return version;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }
}

子类Refrigerator.java

package lian1;

public class Refrigerator extends Dianqi{
    private String doorStyle;
    private String wayRefrigeration;

    public Refrigerator(){
    }

    public Refrigerator(String brand, String version, String color, double price, String doorStyle, String wayRefrigeration) {
        super(brand, version, color, price);
        this.doorStyle = doorStyle;
        this.wayRefrigeration = wayRefrigeration;
    }

    public String getDoorStyle() {
        return doorStyle;
    }

    public void setDoorStyle(String doorStyle) {
        this.doorStyle = doorStyle;
    }

    public String getWayRefrigeration() {
        return wayRefrigeration;
    }

    public void setWayRefrigeration(String wayRefrigeration) {
        this.wayRefrigeration = wayRefrigeration;
    }
}

子类Washer.java

package lian1;

public class Washer extends Dianqi {
    private String powerStyle;
    private int volume;

    public Washer(String brand, String version, String color, double price, String powerStyle, int volume) {
        super(brand, version, color, price);
        this.powerStyle = powerStyle;
        this.volume = volume;
    }
    public Washer(){

    }

    public String getPowerStyle() {
        return powerStyle;
    }

    public void setPowerStyle(String powerStyle) {
        this.powerStyle = powerStyle;
    }

    public int getVolume() {
        return volume;
    }

    public void setVolume(int volume) {
        this.volume = volume;
    }
}

测试类

package lian1;

public class DianqiTest {
    public static void main(String[] args) {
        Refrigerator rg = new Refrigerator("格力","暂无","灰色",1999.99,
                "单门","不详");
        Washer ws = new Washer("海尔","暂无","白色",999.99,"不详",50);
        System.out.println(rg.getBrand()+" "+rg.getVersion()+" "+rg.getColor()+" "+rg.getPrice()
                +" "+rg.getDoorStyle()+" "+rg.getWayRefrigeration());
        System.out.println(ws.getBrand()+" "+ws.getVersion()+" "+ws.getColor()+" "+ws.getPrice()+" "
                +ws.getPowerStyle()+" "+ws.getVolume());
    }
}

运行结果:
在这里插入图片描述

练习2

​ 我们计划为一所体育学校设计一套系统,需要记录以下人员的信息:

  • 教练员:

    • 属性:员工编号、姓名、性别、年龄
    • 行为:吃饭(吃工作餐)
  • 运动员:

    • 属性:学员编号、姓名、性别、年龄、所在班级
    • 行为:吃饭(吃营养餐)

​ 请根据需求,设计、并编码实现:父类“人员类”,子类“教练员类”、子类“运动员类”,并包含共有的属性和行为的定义,由于运动员和教练员的吃饭的内容不同,所以需要设计为“抽象方法”。

父类Person.java

package lian3;

public abstract class Person {
    private String name;
    private String gent;
    private int age;

    public abstract void eat();

    public Person(String name, String gent, int age) {
        this.name = name;
        this.gent = gent;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGent() {
        return gent;
    }

    public void setGent(String gent) {
        this.gent = gent;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

子类Trainer.java

package lian3;

public class Trainer extends Person{
    private String yid;

    public Trainer(String name, String gent, int age, String yid) {
        super(name, gent, age);
        this.yid = yid;
    }

    public String getYid() {
        return yid;
    }

    public void setYid(String yid) {
        this.yid = yid;
    }

    @Override
    public void eat() {
        System.out.println("教练"+getName()+"正在吃工作餐,他的员工编号为"+getYid()+",年龄为"+getAge());
    }
}

子类Sportsman.java

package lian3;

public class Sportsman extends Person {
    private String xid;

    public Sportsman(String name, String gent, int age, String xid) {
        super(name, gent, age);
        this.xid = xid;
    }

    public String getXid() {
        return xid;
    }

    public void setXid(String xid) {
        this.xid = xid;
    }

    @Override
    public void eat() {
        System.out.println("运动员"+getName()+"正在吃营养餐,他的学员编号为"+getXid()+",年龄为"+getAge());
    }
}

测试类

package lian3;

import jicheng.Tager;

public class PersonTest {
    public static void main(String[] args) {
        Trainer t = new Trainer("老王","男",36,"20201467");
        t.eat();
        Sportsman s = new Sportsman("小王","男",22,"20200123");
        s.eat();
    }
}

运行结果:
在这里插入图片描述

练习3

​ 某公司的系统中需要记录两类员工:

  • 员工类:

    • 属性:工号、姓名、年龄
    • 行为:发布通知
  • 经理类:

    • 属性:工号、姓名、年龄、年终奖额
    • 行为:发布通知

    任何员工发布“通知”都统一使用以下格式:

    通知:

​ xxxxxxxxx

​ xxxxxxxxx

​ 必胜环球科技有限公司

父类tongzhi.java

package lian4;

public abstract class Tongzhi {
    private String id;
    private String name;
    private int age;
    public void tongzhi(){
        System.out.println("通知:");
        body();
        System.out.println("\t\t必胜环球科技有限公司");
    }

    public abstract void body();

    public Tongzhi(String id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

子类Jingli.java

package lian4;

public class Jingli extends Tongzhi{
    private int jine;

    public Jingli(String id, String name, int age, int jine) {
        super(id, name, age);
        this.jine = jine;
    }

    public int getJine() {
        return jine;
    }

    public void setJine(int jine) {
        this.jine = jine;
    }

    @Override
    public void body() {
        System.out.println("编号为:"+getId()+"的"+getAge()+"岁的经理"+getName()+"拿着"+jine+"元奖金发布了通知...");
    }
}

子类Yuangong.java

package lian4;

public class Yuangong extends Tongzhi {
    public Yuangong(String id, String name, int age) {
        super(id, name, age);
    }
    @Override
    public void body() {
        System.out.println("编号为:"+getId()+"的"+getAge()+"岁的员工"+getName()+"发布了通知...");
    }
}

测试类Test.java

package lian4;

public class Test {
    public static void main(String[] args) {
        Jingli j = new Jingli("20201216","老王",32,10000);
        j.body();
        Yuangong y = new Yuangong("20201612","小王",25);
        y.body();
    }
}

运行结果:
在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值