zoukankan      html  css  js  c++  java
  • 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();
        }
    }
    
    
  • 相关阅读:
    《算法竞赛入门经典》 例题35 生成元 (Digit Generator, ACM ICPC Seoul 2005,UVa)
    《算法竞赛入门经典》 例题35 生成元 (Digit Generator, ACM ICPC Seoul 2005,UVa)
    《算法竞赛入门经典》 例题35 生成元 (Digit Generator, ACM ICPC Seoul 2005,UVa)
    SVN分支
    SVN分支
    SVN 版本回退
    SVN 版本回退
    如何在excel中取消合并单元格后内容自动填充?
    如何在excel中取消合并单元格后内容自动填充?
    如何让自己像打王者荣耀一样发了疯、拼了命的学习?
  • 原文地址:https://www.cnblogs.com/anke-z/p/12394688.html
Copyright © 2011-2022 走看看