• Chapter09【继承、super、this、抽象类】


    Chapter09【继承、super、this、抽象类】

    第一章 继承

    1.1概述

    集成主要解决的问题是:共性抽取

    父类也可以叫基类、超类

    子类也可以叫做 派生类。

    定义:

    继承:就是子类继承父类的属性行为,使得子类对象具有和父类相同的属性、行为。子类可以直接访问父类中的非私有的属性和行为。

    好处

    1. 提高了代码的复用性
    2. 类与类之间产生了关系

    1.2 继承的格式

    通过static关键字,可以声明一个子类继承另一个父类

    格式:

    class 父类{
    
    	...
    
    }
    
    class 子类 extends 父类{
    
    	...
    
    }
    
    
    

    继承演示,代码如下:

    /*
    定义员工类Empoloyee  为父类 
    */
    class Employee{
       String Name;
        public void work(){
            System.out.println("工作");
        }
    }
    /*
    定义讲师类Teacher 继承员工类Empoloyee
    */
    class Teacher extends Empoloyee{
        //定义一个打印name的方法
        public void printName(){
            System.out.println("name:"+name);
        }
    }
    
    /*
    定义测试类
    */
    public static void main(String[] args){
        //创建一个老师类对象
        Teacher t = new Teacher();
        t.Name = "雷神";
        
        //调用员工的PrintName()方法
        t.printName();//name:雷神
        
        //调用Teacher类继承来的work()方法
        t.work();//工作
    }
    

    区分子类方法中重名的三种变量

    局部变量: 直接写成员方法名

    本类的成员变量: this.成员变量名

    父类的成员变量: super.成员变量名

    //父类
    public class Fu{
        int num = 10;
    }
    //子类
    public class Zi extends Fu{
        int num = 20;
        public void method(){
            int num = 30;
            System.out.println(num);//30
            System.out.println(num);//20
            System.out.println(num);//10
        }
    }
    
    //测试类
    public static void main(String[] args){
        Zi zi = new Zi();
        zi.method;
    }
    
    /*
    结果:
    30
    20
    10*/
    

    1.3 方法重名

    在父子类的继承关系中,创建子类对象,访问成员方法的规则:

    创建的对象是谁,就优先用谁,如果没有就向上找。

    //父类
    public class Fu{
        public void methodFu{
        	System.out,println("子类方法执行!");
        }
        
        public void method(){
            System.out,println("父类重名方法执行!");
        }
    }
    
    //子类
    public class Zi extend Fu {
        public void methodZi{
        	System.out,println("子类方法执行!");
        }
        
        public void method(){
            System.out,println("子类重名方法执行!");
        }
    }
    
    //测试类
    public static void main(String[] args){
        
        Zi zi = new Zi();
        
        zi.methodFu();
        zi.methodZi();
        
        zi.method();
        
        /*结果:
        子类的方法执行了
    	父类方法执行了
    	子类重名方法执行!
        
        */
    } 
    

    1.4 成员方法重名 -- 重写(override)

    如果子类父类中出现重名的成员方法,这时的访问是一种特殊情况,叫做方法重写(override)

    概念:

    子类中出现与父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效

    果,也称为重写或者复写。

    声明不变,重新实现

    特点:

    创建的是子类对象,则优先用子类方法。

    重写(override):方法的名称一样,参数列表【也一样】。也叫覆盖、复写

    重载(overload):方法名称一样,参数列表【不一样】。

    注意事项

    1. 子类方法覆盖父类方法,返回值类型、函数名和参数列表都要一模一样

      @override:写在方法前面,用来检测是不是有效的正确覆盖重写

      这个注释就算不写,只要满足要求,也是正确的覆盖重写

    2. 子方法的返回值必须【小于等于】父方法的返回值范围。

      小扩展提示:java.lang.Object类是所有类的公共最高父类(祖宗类),java.lang.String就是object的子类

    3. 子类方法的权限必须【大于等于】父类方法的权限修饰符

    4. 小扩展提示:public > protected > (defoult) 什么都不写>private

      备注:(default)不是关键字default,而是什么都不写,留空。

    /*
    重写(override):方法的名称一样,参数列表【也一样】。也叫覆盖、复写
    */
    public class Fu{
        public void method(){
            System.out.println("Fu show");
        }
    }
    
    public class Zi extends Fu{
         public void method(){
            System.out.println("Zi show");
        }
    }
    
    public static void main(String[] args){
        Zi zi = new Zi();
        zi.method();//zi show
    }
    
    /*
    重载(overload):方法名称一样,参数列表【不一样】。
    */
    public void bark(){
        System.out.println("woof");
    }
    public void bark(int num){
        for(int i = 0;i<num;i++){
            System.out.println("woof");
        }
    }
    

    小结:

    重写(override):方法名参数都一样。

    重载(overload):方法名相同,参数不同。

    设计原则:

    对于已经投入使用的类,尽量不要进行修改。推荐定义一个新的类,来重复利用其中的共性内容,并且添加改动新内容

    子类可以根据需要,定义特定于自己的行为。既沿袭了父类的功能名称,又根据子类的需要重新实现父类方法,从 而进行扩展增强。比如新的手机增加来电显示头像的功能

    代码如下:

    //父类
    class Phone{
        public void call(){
            System.out.println("打电话");
        }
        public void send(){
            System.out.println("发短信");
        }
        public void show(){
            System.out.println("现实号码");
        }
    }
    //子类
    class NewPhone{
        @Override
        public void show(){
            super.show();
            System.out.println("显示号码");
            System.out.println("显示头像");
        }
    }
    //测试类
    public static void main(String[] args){
        Phone phone = new Phone();
        phone.call();//打电话
        phone.send();//发短信
        phone.show();//显示号码
        
        NewPhone newphone = new NewPhone();
        newphone.call();//打电话
        newphone.send();//发短信
        newphone.show();//显示号码  显示号码  显示头像
        
    }
    
    

    访问特点:

    继承关系中,父子构造方法的访问特点

    1. 子类构造方法中有一个默认隐含的“super();”方法调用,所有一定是先调用的父类构造,然后执行子类的构造。

    2. 子类构造可以通过super关键字来调用父类重载结构。

    3. super的父类构造调用,必须是子类构造方法的第一个语句。

      不能一个子类构造调用多次super构造。

    总结:

    子类必须调用父类构造方法,不写则赠送super();写了则用指定的super调用,super只能有一个,还必须是第一个。

    1.5 super和this

    super关键字访问父类内容

    三种用法

    1. 在子类的成员方法中,访问父类的成员变量。

      格式:super.成员变量

      class Fu{
          int num = 10;
      }
      class Zi extends Fu{
          int num = 20;
          public void methodZi(){
              System.out.println(num);//10
              System.out.println(super.num);//20 父类中的num
          }
      }
      
    2. 在子类的成员方法中,访问父类的成员方法。

      格式:super.方法名();

      class Fu{
          public void method(){
               System.out.println("父类方法");
      }
      class Zi exteds Fu(){
          public void method(){
              super.method();//访问父类的method
               System.out.println("子类方法");
      }
      
    3. 在子类的构造方法中,访问父类的构造方法

    class Fu{
        
    }
    class Zi exteds Fu(){
        public zi(){
            super();//访问父类的构造方法
        }
        
    }
    

    this关键字用来访问本类的内容

    三种用法:

    1. 在本类成员方法中,访问本类的成员变量
    class Fu{
        int num = 10;
    }
    class Zi extends Fu{
        int num = 20;
        
        public void method(){
            int num = 30;
            System.out.println(num);//30
            System.out.println(this.num);//20
            System.out.println(super.num);//10
        }
    }
    

    2.在本类成员方法中,访问本类中的另一个成员方法。

    public void method(){
        System.out.println("AAA");
    }
    public void methodB(){
        this.method();
        System.out.println("DDD");
    }
    

    3.在本类的构造方法中,访问本类的另一个构造方法

    注意:

    • this(...)调用必须也是构造方法的第一个语句,唯一一个。
    • super和this两种构造调用,不能同时使用。
    public Zi(){
        this(66);//本类的无参构造,调用本类的有参构造
    }
    public zi(int n){
        
    }
    

    图解

    1.6继承的特点

    1. java只支持单继承,不支持多继承。

      //一个类只能有一个父类
      class A{}
      class C extends A{}//对
      class C extends A,b...//错
      
    2. java支持多层继承(继承体)

      注意:

      顶层父类是Object类,所有类都继承Object,作为父类

      class A{}
      class B extends A{}
      class C extends B{}
      
    3. 一个子类的直接父类是唯一的,但是一个父类可以拥有多个子类。

      class A{}
      class B extends A{}
      class C extends A{}
      

    第二章 抽象类

    2.1概述

    父类中的方法,被它的子类们重写,子类各自的实现都不尽相同。那么父类的方法声明和方法主体,只有声明还有 意义,而方法主体则没有存在的意义了。我们把没有方法主体的方法称为抽象方法。Java语法规定,包含抽象方法 的类就是抽象类

    定义

    抽象方法 : 没有方法体的方法。

    抽象类:包含抽象方法的类

    2.2 抽象方法与抽象类

    通过abstract关键字

    抽象方法

    使用abstract关键字修饰。只有一个方法名,没有方法体。

    格式:

    修饰符 abstract 返回值类型 方法名(参数列表);
    
    public abstract void run();
    

    抽象类

    如果一个类包含抽象方法,那么该类型必须是抽象类

    abstract class 类名{
        
    }
    
    public abstract class Anima{
        public abstract void run();
    }
    

    举例代码如下:

    //父类
    public abstract Animal{
        public abstract void eat();
    }
    //子类
    public class Cat extends Animal{
        public void eat(){
            System,out.println("猫吃鱼!");
        }
    }
    //测试类
    public class Main{
        public static void main(String[] args){
            Cat cat = new cat();
            cat.eat();//猫吃鱼
        }
    }
    

    注意事项

    关于抽象类的使用,以下为语法上要注意的细节,虽然条目较多,但若理解了抽象的本质,无需死记硬背。

    1. 抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。

    理解:假设创建了抽象类的对象,调用抽象的方法,而抽象方法没有具体的方法体,没有意义。

    1. 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。

    理解:子类的构造方法中,有默认的super(),需要访问父类构造方法。

    1. 抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。

      理解:未包含抽象方法的抽象类,目的就是不想让调用者创建该类对象,通常用于某些特殊的类结构设 计。

    2. 抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象 类。

      理解:假设不重写所有抽象方法,则类中可能包含抽象方法。那么创建对象后,调用抽象的方法,没有 意义。

    第三章 继承的综合案例

    3.1 综合案例:群主发普通红包

    群主发普通红包。某群有多名成员,群主给成员发普通红包。普通红包的规则:

    1. 群主的一笔金额,从群主余额中扣除,平均分成n等份,让成员领取。

    2. 成员领取红包后,保存到成员余额中。

    请根据描述,完成案例中所有类的定义以及指定类之间的继承关系,并完成发红包的操作。

    3.2 案例分析

    根据描述分析,得出如下继承体系:

    3.3 案例实现

    定义用户类:

    public class User {
    
        private String name;//姓名
        private int money;//余额
    
        //空参构造
        public User() {
        }
        //全参构造
        public User(String name,int money){
            this.name = name;
            this.money = money;
        }
    
        //展示余额
        public void show(){
            System.out.println("姓名:"+name + ",余额:"+money);
        }
        //get、set访问成员变量
    
        public void setName(String name){
            this.name = name;
        }
        public String getName(){
            return name;
        }
        public void setMoney(int money){
            this.money = money;
        }
        public int getMoney(){
            return money;
        }
    }
    
    

    // 定义群主类

    public class Manager extends User{
    //群主类
    
        public Manager(){
    
        }
        public Manager(String name,int money){
            super(name,money);
        }
        public ArrayList<Integer> send (int totalMoney,int count){
            //需要一个集合,用来存储若干个红包的金额
            ArrayList<Integer> redList = new ArrayList<>();
    
            //看一下群主有多少钱
            int leftMoney = super.getMoney();
            if (totalMoney > leftMoney){
                System.out.println("余额不足");
                return redList;// 返回空集合
            }
    
            //扣钱,其实就是重新设置余额
            super.setMoney(leftMoney-totalMoney);
    
            //发红包需要平均拆成count份
            int avg = totalMoney / count;
            int mod = totalMoney % count;//余数,就是剩下的零头
    
            //除不开的零头,包在最后一个红包中
            //下面把红包一个一个方到集合中
            for (int i = 0; i < count - 1; i++) {
                redList.add(avg);
            }
    
            //最后一个红包
            int last = avg + mod;
            redList.add(last);
    
            return redList;
        }
    }
    
    

    定义成员类

    public class Menber extends User {
        //空参
        public Menber(){
    
        }
        //全参
        public Menber(String name ,int money){
            super(name,money);
    
        }
    
        public void receive(ArrayList<Integer> list){
            //从多个红包当中随机抽取一个,给自己
            //随机获取一个集合当中的索引
            int index = new Random().nextInt(list.size());
            //根据索引,从集合当中删除,并获得被删除的红包,给我自己
            int delta = list.remove(index);
            //当前成员有多少钱
            int money = super.getMoney();
            //加法,并且重新设置回去
            super.setMoney(money+delta);
        }
    }
    
    

    测试类

    public class MainRedPacket {
        public static void main(String[] args) {
    
            Manager manager = new Manager("群主",100);
    
            Menber one = new Menber("成员A",0);
            Menber two = new Menber("成员B",0);
            Menber three = new Menber("成员C",0);
    
            manager.show();
            one.show();
            two.show();
            three.show();
            System.out.println("=============");
    
            //群主共发20元红包,分成3个红包
            ArrayList<Integer> redList = manager.send(20,3);
            //三个普通成员收红包
            one.receive(redList);
            two.receive(redList);
            three.receive(redList);
    
            manager.show();
            one.show();
            two.show();
            three.show();
        }
    }
    
    
  • 相关阅读:
    关于程序中以时间判断接收数据结束时,接收数据长度设置为1时,出现接收不全的问题解释。
    stm32 外部8M晶振 改为12M的方法
    django iis 部署
    电信NB卡
    socketserver
    APScheduler简介
    三极管开关电路
    mysql授权
    解决VMware无法共享ubuntu虚拟机文件
    Python解析yaml配置文件
  • 原文地址:https://www.cnblogs.com/anke-z/p/12394688.html
Copyright © 2020-2023  润新知