java09 继承(覆盖重写、super、this)抽象类





3.继承

      继承是多态的前提,面向对象的三大特征:封装、继承、多态

image

继承可以理解为抽取共性的关键点,如上图所示。

定义:

父类:  public class 父类名称{               子类:public class 子类名称 extends 父类名称{

        代码块                                                   代码块

}                                                            }

唯一一个标识  extends  。

image

从而实现了代码复用的作用。

3.0.1.父类与子类的成员变量各自使用范围:

父类可以使用父类的成员变量,而子类不光可以使用子类成员变量 还可以使用父类的成员变量。父类与子类成员变量可以重名。

3.0.2.访问父类成员变量的方法:

  • 直接通过子类对象访问成员变量:

规则:等号左边是谁,则优先用谁,否则没有则向上查找。

  • 间接通过成员方法访问成员变量:

规则:子类对象点(调用)的方法是谁,则优先使用谁,没有则向上找。

image

至此,出现三种变量:局部变量、子类成员变量、父类成员变量,因此在子类的成员方法中进行以下三种方法区分:即

  • 局部变量直接用,子类成员变量用this.,

  • 而父类成员变量用super进行区分。

  • 调用成员方法的对象是子类,则优先用子类的成员方法,否则就向上找。

image



3.1.继承关系中成员方法名称一样就存在覆盖重写

覆盖重写:override 发生在继承关系中,方法名称一样,参数列表也一样,

方法重载:overload 方法名称一样,参数列表不同。

3.1.1.方法的覆盖重写使用过程中有几点需要特别十分关注

  • 父类与子类的成员方法,必须同名和同参数,可使用@override起到安全检测作用。
  • 子类的返回值范围必须小于父类的返回值。
  • 子类的方法权限必须大于等于父类的方法权限 public>protected>(default)>private

3.1.2.方法的覆盖重写的应用场景

      假如 现在有个需求,将老款手机中的来电提醒功能,增加手机姓名等,这时不方便写过去所有用户的老程序,此事扩展其新方法,就需要使用覆盖重写的子类方法。

image

3.1.3父类构造方法的访问特点:


    构造方法是定义在java类中的一个用来初始化对象的方法,体现在:所谓的创建一个对象就是开辟一个内存空间,初始化是指给对应属性赋初值。

  1 public class Student
  2 {
  3     public String name;
  4     public int age;
  5     public Student()
  6     {
  7         //默认的构造方法,其中name的初值是null,age的初值是0;
  8         //当然你也可以给定一个固定的值
  9         //name="name";
 10         //age=20;
 11     }
 12     //构造方法重载,完成对应属性的初始化
 13     public Student(String name,int age)
 14     {
 15         this.name=name;
 16         this.age=age;
 17         //其中name,age的初值是参数中传入的值
 18     }
 19 }

特点:子类构造必须调用父类构造,默认赠送super();调用无参,否则手写super(传参)调用父类有参构造也就是父类重载的构造方法

1.子类构造方法方法体内 必须调用父类构造方法,没有明确写super():,那么将默认赠送。

2.子类构造方法可以用super关键字来调用父类重载构造

3.子类构造方法用super调用父类构造方法时,必须排行第一句

image

      构造方法是一种特殊的方法,它是一个与类同名的方法。对象的创建就是通过构造方法来完成,其功能主要是完成对象的初始化。当类实例化一个对象时会自动调用构造方法。

构造方法和成员方法的区别

    A:格式区别
           构造方法和类名相同,并且没有返回类型,也没有返回值。
           普通成员方法可以任意起名,必须有返回类型,可以没有返回值。
     B:作用区别
            构造方法用于创建对象,并进行初始化值。
            普通成员方法是用于完成特定功能的。

     C:调用区别
            构造方法是在创建对象时被调用的,一个对象建立,只调用一次相应构造函数。
            普通成员方法是由创建好的对象调用,可以调用多次


3.2.super关键字用法

  • A 子类的成员方法中,super调用父类的成员变量 super.父类成员变量名
  • B 子类的成员方法中,super调用父类的成员方法 super.父类成员方法名
  • C 子类的构造方法中,super调用父类的构造方法 super(可传参);

super :代表父类的存储空间标识(可以理解为父亲的引用)。 也就是使用super关键字访问父类内容。它与this关键字的区别如下:

this.成员变量 ‐‐ 本类的

super.成员变量 ‐‐ 父类的

this.成员方法名() ‐‐ 本类的

super.成员方法名() ‐‐ 父类的

3.3.this关键字

3.3.1含义

this :代表当前对象的引用(谁调用就代表谁)。 也就是使用this关键字访问本类中,或是子类中使用或是父类中使用。

this.成员变量 ‐‐ 本类的

super.成员变量 ‐‐ 父类的

this.成员方法名() ‐‐ 本类的

super.成员方法名() ‐‐ 父类的

3.3.2this关键字的3个用法和4个关键点

  • 用法:

在本类的成员方法中,访问本类的成员变量

在本类的成员方法中,访问本类的另外一个成员方法

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

  • 关键点:

this调用也得是构造方法中的第一个语句。

构造方法中,this调用不能没有尽头,至少有一个构造方法中没有调用this。

成员方法中,this可以在全部成员方法循环调用。


效果图如下:

image


  1 package d.d.d;
  2 public class zi extends fu {
  3     int num =20;
  4     public void showNum(){
  5         int num = 10;
  6         System.out.println(num);//局部变量,访问本方法中局部变量 num = 10;
  7         System.out.println(this.num);//this关键字访问本类的成员变量num = 20
  8         System.out.println(super.num);//super关键字访问父类num = 30
  9     }
 10     public void methodA() {    // 成员方法A
 11         System.out.println("aaa");
 12         this.methodB();
 13     }
 14     public void methodB() {    // 成员方法B
 15         methodA();//在成员方法methoB中调用methodA,另外一种方法是this.methodA();是强调作用
 16         this.methodA();//与methodA();一样,只是起到强调作用
 17         System.out.println("bbb");
 18     }
 19      public zi(){   // 构造方法zi();
 20         //this.zi(); 这种是错误写法
 21         this(123);//本类的无参构造,调用本类的有参构造
 22     }
 23     public zi(int n){    // 构造方法zi(n);
 24         this(12,3);
 25     }
 26     public zi(int n,int b){    // 构造方法zi(n,m);
 27         //this(3); 不可以全部都有this,至少有一个构造方法
 28     }
 29 
 30 }
 31 
 32 
  1 package d.d.d;
  2 
  3 public class fu {//父类
  4     int num = 30;
  5 }
  6 

3.3.3.内存图的变化

image

  1 package d.d.d;
  2 
  3 public class demo {
  4     public static void main(String[] args) {
  5         zi zi = new zi();
  6         zi.show();
  7         zi.method();
  8     }
  9 }
  1 package d.d.d;
  2 
  3 public class fu {
  4     int num = 10;
  5     public void  method(){
  6         System.out.println("父类方法");
  7     }
  8 }
  9 
  1 package d.d.d;
  2 public class zi extends fu {
  3     int num =20;
  4     @Override
  5     public void method(){ //与父类成员方法一样,叫覆盖重写
  6         super.method();// 调用父类成员方法
  7         System.out.println("子类方法");
  8     }
  9     public void show(){
 10         int num = 30;
 11         System.out.println(num);// 输出局部变量,num = 30;
 12         System.out.println(this.num);// 输出本类成员变量,num = 20;
 13         System.out.println(super.num);// 输出父类成员变量,num = 10;
 14 
 15     }
 16 
 17 }
 18 

3.3.4java的继承的特征

  • java语言是单继承,一个类的直接父类只能有唯一一个
  • java语言可以多级继承
  • java语言一个父类,可以有多个子类

image


4.抽象类

      了解下什么叫抽象,假设提问一个图形的面积计算,那么对于三角形、圆形、长方形等等,均有不同的计算方法。所以这个方法是一个抽象方法,具体到一种图形就行。如果父类方法不确定如何进行,也就是具体执行方式不确定,那么就是抽象方法

05-抽象的概念

4.1.抽象方法的定义

抽象方法:就是在返回值前面加上 abstract 关键字,然后去掉大括号,直接小括号结束;

抽象类:也就是抽象方法所在的类就是抽象类,定义抽象类就是在class前面加上abstract;

语法:

public abstract class 类名{   //抽象类就是在class前面加上abstract

      public abstract void eat(); //返回值前面加上 abstract 关键字,然后去掉大括号,直接小括号结束;

}

1585212939(1)

  1 package e.e.e;
  2 
  3 public abstract class E {//抽象方法
  4     public abstract void eat();//抽象方法
  5     //这是普通方法
  6     public void normamethod(){
  7 
  8     }
  9 }

4.2.抽象方法的使用方法和注意事项

  • 不能直接创建new抽象类对象
  • 必须使用一个子类来继承抽象父类
  • 子类必须覆盖重写抽象父类当中的所有的抽象方法
  • 覆盖重写(实现):子类去掉抽象方法中的abstract关键字,然后补上方法体大括号。

image

  1 package e.e.e;
  2 
  3 public abstract class animail {//抽象方法
  4     public abstract void eat();//抽象方法
  5     //这是普通方法
  6     public void normamethod(){
  7 
  8     }
  9 }
  1 package e.e.e;
  2 
  3 public class cat extends animail {
  4     @Override
  5     public  void eat(){
  6         System.out.println("猫吃鱼");
  7     }
  8 
  9 }
 10 
  1 package e.e.e;
  2 
  3 public class demo {
  4     public static void main(String[] args) {
  5         cat cat = new cat();
  6         cat.eat();
  7     }
  8 }
  9 


4.3注意事项。

  • 抽象类不能创建对象,如果创建,编译无法通过而报错,只能创建其非抽象子类的对象,也就是说如果创建类抽象类的对象,调用抽象的方法,而抽象方法没有具体方法体,没有意义

image

  • 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的,也就是说子类的构造方法中,有默认的super()会访问父类的构造方法,进行父类成员初始化。1.抽象父类构造方法先执行,然后子类的构造方法执行,这个父类的构造方法要执行,必须用super()调用。 2.子类即便没有构造方法,那么父类的无参构造方法也会默认执行。

image

  • 抽象类中,不一定包含抽象方法,但有抽象方法的必须是抽象类。未包含抽象方法的抽象类,是不想让调用创建抽象方法的对象,通常用于某种特别结构设计,设计模式中的适配器模式就可以使用这样的。


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

image

5.案例:

5.3.群主发普通红包

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

  • 1. 群主的一笔金额,从群主余额中扣除,平均分成n等份,让成员领取。
  • 2. 成员领取红包后,保存到成员余额中。

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

分析:首先有个群,群主是发送红包,群主自己不抢红包,群主金额会减少,成员抢红包,抢到金额进入自己腰包约

image

  1 public class User {
  2     private  String name;//姓名
  3     private int money;// 余额
  4 
  5     public User() {// 无参构造  alt+ insert  constructor 啥都不选快速生成
  6     }
  7 
  8     public User(String name, int money) {// 有参构造  alt+ insert  constructor 全选选快速生成
  9         this.name = name;
 10         this.money = money;
 11     }
 12     //展示一下当前用户多少钱
 13     public void show(){
 14         System.out.println("我叫:" + name + "我有多少钱" + money);
 15     }
 16 
 17     public String getName() {
 18         return name;
 19     }
 20 
 21     public void setName(String name) {
 22         this.name = name;
 23     }
 24 
 25     public int getMoney() {
 26         return money;
 27     }
 28 
 29     public void setMoney(int money) {
 30         this.money = money;
 31     }
 32 }
 33 
  1 import java.util.ArrayList;
  2 //群主的类
  3 public class Manager extends User{
  4     // 写默认构造和有参构造即可,默认有super();
  5     public Manager(){
  6 
  7     }
  8 
  9     public Manager(String name, int money) {//叫什么名字、多少钱
 10         super(name, money);//参数传递给父类
 11     }
 12     public ArrayList<Integer> send (int totalMoney,int count){        // 总共要发多少钱,要发几份
 13         //首先需要一个集合,存储若干个红包的金额
 14         ArrayList<Integer> redList = new ArrayList<>();
 15         // 首先看下群主有多少钱
 16         int leftMoney = super.getMoney();//群主当前余额。
 17         if(totalMoney > leftMoney){
 18             System.out.println("余额不足");
 19             return redList;// 返回空集合
 20         }
 21         // 扣钱 就是重新设置余额
 22         super.setMoney(leftMoney - totalMoney);// super是父类方法,将余额返回送进父类
 23         //发红包需要拆分count分
 24         int avg = totalMoney / count;
 25         int mod = totalMoney % count; // 余数 也就是取模
 26 
 27         // 除不开的零头放在最后一个红包中
 28         // 下面把红包一个一个放在集合中
 29         for (int i = 0; i < count - 1; i++) {//最后一个红包单独处理
 30             redList.add(avg);
 31         }
 32         // 最后一个红包
 33         int last = avg + mod;
 34         redList.add(last);
 35         return redList;
 36 
 37     }
 38 }
 39 
  1 import java.util.ArrayList;
  2 import java.util.Random;
  3 
  4 
  5 public class Member extends User{
  6     public Member() {
  7     }
  8 
  9     public Member(String name, int money) {
 10         super(name, money);
 11     }
 12     public void receive(ArrayList<Integer> list){//红包已经在集合中
 13         // 从多个红包当中随便抽泣一个红包,给自己,也就是随机获取集合当中的索引变化。
 14         int index = new Random().nextInt(list.size());// random是匿名对象,范围是不能超过集合长度,最高到size-1为止
 15         //根据索引,从集合中删除,并且得到被删除的红包,给自己
 16         int delta = list.remove(index);//remove返回的是被删除的值,也就是某个抢到的红包钱
 17         // 当前成员自己本来多少钱
 18         int money = super.getMoney();
 19         //最后成员多少钱,也就是加上后,重新设置回去。
 20         super.setMoney(money + delta);
 21 
 22 
 23     }
 24 }
 25 


  1 import java.util.ArrayList;
  2 
  3 public class MainRedPacket {
  4     public static void main(String[] args) {
  5         Manager manager = new Manager("群主",101);
  6         Member member1 = new Member("bingo1",2);
  7         Member member2 = new Member("bingo2",2);
  8         Member member3 = new Member("bingo3",2);
  9         Member member4 = new Member("bingo4",2);
 10         manager.show();
 11         member1.show();
 12         member2.show();
 13         member3.show();
 14         member4.show();
 15         // 装群主发红包的集合怎么来的呢
 16         ArrayList<Integer> redList = manager.send(20,4);
 17         // 四个人去收红包
 18         member1.receive(redList);
 19         member2.receive(redList);
 20         member3.receive(redList);
 21         member4.receive(redList);
 22 
 23         manager.show();
 24         member1.show();
 25         member2.show();
 26         member3.show();
 27         member4.show();
 28     }
 29 }
 30 
posted @ 2020-03-26 13:07  芒果侠  阅读(485)  评论(0编辑  收藏  举报