为什么要有继承

多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那一个类即可。其中,多个类可以称为子类,单独那一个类称为父类超类或者基类

继承的概念

继承:就是子类继承父类的属性行为,使得子类对象具有与父类相同的属性、相同的行为。子类可以直接访问父类中的非私有的属性和行为。继承描述的是事物之间的所属关系,这种关系是: is-a 的关系。继承的关系中,“子类就是一个父类”,也就是说子类可以被当做父类看待。例如,兔子属于食草动物,食草动物属于动物。可见,父类更通用,子类更具体。我们通过继承,可以使多种事物之间形成一种关系体系。继承主要解决的问题是共性抽取。

好处

  • 提高代码的复用性
  • 类与类之间产生了关系,是多态的前提

继承关系当中的特点

  • 子类拥有父类中非私有的属性和行为
  • 子类还可以拥有自己独有的属性和行为

继承的格式

通过 extends 关键字,可以声明一个子类继承另外一个父类,定义格式如下:

注意:父类只是一个普通的类

代码举例

定义父类

package MyCode.demo01;

// 定义一个父类
public class MyFather {
    //父类中的成员变量
    public int age = 18;

    //父类中的成员方法
    public void method() {
        System.out.println("我是父类中的方法");
    }
}

定义子类

package MyCode.demo01;

// 定义子类MySon继承MyFather
public class MySon extends MyFather {
}

定义测试类

package MyCode.demo01;

public class MyTest {
    public static void main(String[] args) {
        //创建子类对象
        MySon son = new MySon();
        //子类里面什么代码都没有,但是继承了父类中非私有的方法和属性
        son.method();
        System.out.println(son.age);
    }
}

代码执行后的结果

继承中成员变量的访问特点

创建父类对象

  • 只能使用父类的成员变量,没有任何子类的成员变量

创建子类对象

  • 子类对象可以使用本类中的成员变量或者使用父类中非私有的成员变量
  • 如果子类父类中出现不重名的成员变量,这时子类对象可以根据不同的成员变量名来访问需要的成员变量。
  • 如果子类父类中出现重名的成员变量,这时子类对象有2种访问方式

             访问方式1:直接通过子类对象访问成员变量:等号左边是谁,就优先用谁,没有则向上(父类)找。
             访问方式2:间接通过成员方法访问成员变量:该方法属于谁,就优先用谁,没有则向上(父类)找

继承中成员方法的访问特点

创建父类对象

  • 只能使用父类的成员方法,没有任何子类的成员方法

创建子类对象

  • 子类对象可以使用本类中的成员方法或者使用父类中非私有的成员方法
  • 访问成员方法的规则:创建的对象是谁,就优先用谁,如果没有则向上(父类)找。

方法重写 (Override)

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

  • 方法重写 :子类中出现与父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效 果,也称为重写或者复写。简单理解:声明不变,重新实现

方法重写的注意事项:

1. 必须保证父子类之间方法的名称相同,参数列表也相同。

  • tips:@Override:写在方法前面,用来检测是不是有效的正确覆盖重写。这个注解就算不写,只要满足要求,也是正确的方法覆盖重写。

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

  • tips:java.lang.Object类是所有类的公共最高父类(祖宗类),java.lang.String就是Object的子类。

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

  • tips:public > protected > (default) > private    备注:(default)不是关键字default,而是什么都不写,留空。

重写的应用

子类可以根据需要,定义特定于自己的行为。既沿袭了父类的功能名称,又根据子类的需要重新实现父类方法,从 而进行扩展增强。设计原则:对于已经投入使用的类,尽量不要修改,推荐一个新的类,来重复利用其中共性内容,添加新的内容。

代码举例

定义老款手机

package MyCode.demo02;

// 本来的老款手机
public class Phone {

    public void call() {

        System.out.println("打电话");
    }

    public void send() {
        System.out.println("发短信");
    }

    public void show() {
        System.out.println("显示号码");
    }

}

定义新款手机类,方法覆盖重写应用。

package MyCode.demo02;

// 定义一个新手机,使用老手机作为父类
public class NewPhone extends Phone {

    //重写父类的来电显示号码功能,并增加自己的显示姓名和图片功能
    @Override
    public void show() {
        //调用父类已经存在的功能使用super
        super.show();
        //增加自己特有显示姓名和图片功System.out.println("显示来电姓名");
        System.out.println("显示头像");
    }
}

定义测试类

package MyCode.demo02;

public class Demo01Phone {
    public static void main(String[] args) {

        // 创建子类对象
        NewPhone np = new NewPhone();

        //调用继承下来的方法
        np.call();
        np.send();
        // 调用子类重写的方法
        np.show();

    }
}

代码执行后的结果

Java关键字this和super用法总结

this关键字含义

  • this :代表当前对象的引用(谁调用就代表谁)。

super的含义

  • super :代表父类的存储空间标识(可以理解为父亲的引用)。

super关键字用来访问父类内容,用法有三种:

  1. 在子类的成员方法中,访问父类的成员变量。格式:super.成员变量名
  2. 在子类的成员方法中,访问父类的成员方法。格式:super.成员方法名
  3. 在子类的构造方法中,访问父类的构造方法。格式:super(参数列表)

this关键字用来访问本类内容,用法也有三种:

  1. 在本类的成员方法中,访问本类的成员变量。              格式:this.成员变量名
  2. 在本类的成员方法中,访问本类的另一个成员方法。   格式:this.成员方法名()
  3. 在本类的构造方法中,访问本类的另一个构造方法。   格式:this(参数列表)

第三种用法当中要注意:

  • this(...)调用也必须是构造方法的第一个语句,唯一一个。
  • super和this两种构造调用,不能同时使用。​​​​​​​

代码举例

package MyCode.demo03;

class Animal {
    public void eat() {
        System.out.println("animal : eat");
    }
}

创建子类Cat

package MyCode.demo03;

class Cat extends Animal {
    public void eat() {
        System.out.println("cat : eat");
    }

    public void eatTest() {
        // this 调用本类的方法
        this.eat();
        // super 调用父类的方法 }
        super.eat();
    }
}

创建测试类

package MyCode.demo03;

public class Test {
    public static void main(String[] args) {
        //创建父类对象Animal
            Animal a = new Animal();
            a.eat();
            //创建子类对象
            Cat c = new Cat();
            c.eatTest();
        }
    }

代码执行后的结果

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

  • 构造方法的名字是与类名一致的。所以子类是无法继承父类构造方法的。
  • 子类构造方法当中有一个默认隐含的“super()”调用,所以一定是先调用的父类构造,后执行的子类构造方法
  • 子类构造可以通过super关键字来调用父类重载构造。
  • super的父类构造调用,必须是子类构造方法的第一个语句。不能一个子类构造调用多次super构造。
  • 总结:子类构造方法必须调用父类构造方法,不写则赠送super();写了则用写的指定的super调用,super只能有一个,还必须是第一个。

父类空间优先于子类对象产生

在每次创建子类对象时,先初始化父类空间,再创建其子类对象本身。目的在于子类对象中包含了其对应的父类空间,便可以包含其父类的成员,如果父类成员非private修饰,则子类可以随意使用父类成员。代码体现在子类的构造方法调用时,一定先调用父类的构造方法。

继承的特点

Java只支持单继承,不支持多继承。

//一个类只能有一个父类,不可以有多个父类。
class C extends A{} //ok
class C extends A,B... //error

Java支持多层继承(继承体系)。

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

子类和父类是一种相对的概念。tips:顶层父类是Object类。所有的类默认继承Object,作为父类。

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

群主发普通红包。某群有多名成员,群主给成员发普通红包。普通红包的规则:
  • 群主的一笔金额,从群主余额中扣除,平均分成n等份,让成员领取。
  • 成员领取红包后,保存到成员余额中。请根据描述,完成案例中所有类的定义以及指定类之间的继承关系,并完成发红包的操作。

案例分析

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

代码实现

定义User类

package MyCode.demo05;

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);
    }

    public String getName() {
        return name;
    }

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

    public int getMoney() {
        return money;
    }

    public void setMoney(int money) {
        this.money = money;
    }
}

定义Manager类

package MyCode.demo05;

import java.util.ArrayList;

// 群主的类
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;
    }
}

定义Member类

package MyCode.demo05;

import java.util.ArrayList;
import java.util.Random;

// 普通成员
public class Member extends User {

    public Member() {
    }

    public Member(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);
    }
}

定义测试类

package MyCode.demo05;

import java.util.ArrayList;

public class MainRedPacket {

    public static void main(String[] args) {
        Manager manager = new Manager("群主", 100);

        Member one = new Member("成员A", 0);
        Member two = new Member("成员B", 0);
        Member three = new Member("成员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(); // 100-20=80
        // 6、6、8,随机分给三个人
        one.show();
        two.show();
        three.show();
    }

}

代码执行后的结果

Java之继承性的更多相关文章

  1. java的继承性

    在java继承中,子类也称为派生类,父类也称为基类或者超类,基本语法 :子类 extends 父类{} 实现一个简单的继承类: class Person{ private String name; p ...

  2. java 面向对象(十二):面向对象的特征二:继承性 (一) 前言

    1.为什么要有类的继承性?(继承性的好处) * ① 减少了代码的冗余,提高了代码的复用性 * ② 便于功能的扩展 * ③ 为之后多态性的使用,提供了前提图示: 2.继承性的格式:class A ext ...

  3. Java学习---基础知识学习

    2016-07-23  周六 利用键盘输入的时候需要抛出异常 ,直接快捷键 ctrl + 1 ;定义数组 int score[] = new int[4]  ;  只有4个数字BufferedRead ...

  4. 浅谈Java三大特性之继承

    前言 简单用伪代码去介绍一些 父类与子类的构造函数问题 others 前言 类的继承性是面向对象语言的基本特性,多态性前提是继承性.Java 支持继承性和多态性.——Java从小白到大牛 继承:三大特 ...

  5. JAVASE(九)面向对象特性之 : 继承性、方法重写、关键字super、

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 1.继承性 1.1 为什么要类的继承性?(继承性的好处) ①减少了代码的冗余,提高了代码的复用性:②更好 ...

  6. java 面向对象(二十四):interface:接口

    interface:接口1.使用说明: 1.接口使用interface来定义 * 2.Java中,接口和类是并列的两个结构 * 3.如何定义接口:定义接口中的成员 * * 3.1 JDK7及以前:只能 ...

  7. Java基础语法,常用知识复习

    1.开发环境搭建 1.1JDK.JRE.JVM.的关系 JDK = JRE + 开发工具集(例如javac编译工具集等) JRE = JVM + Java SE 标准类库 2.基本语法 2.1.jav ...

  8. 尚硅谷Java——宋红康笔记【day11-day18】

    day11 Eclipse中的快捷键: * 1.补全代码的声明:alt + / * 2.快速修复: ctrl + 1 * 3.批量导包:ctrl + shift + o * 4.使用单行注释:ctrl ...

  9. <Android Framework 之路>多线程

    多线程编程 JAVA多线程方式 1. 继承Thread线程,实现run方法 2. 实现Runnable接口 JAVA单继承性,当我们想将一个已经继承了其他类的子类放到Thread中时,单继承的局限就体 ...

随机推荐

  1. uni-app微信小程序开发之引入腾讯视频小程序播放插件

    登录微信小程序管理后台添加腾讯视频播放插件: 正式开始使用腾讯视频小程序插件之前需先在微信公众平台 -> 第三方设置 -> 插件管理处添加插件,如下图所示: 在uni-app中引入插件代码 ...

  2. PostgreSQL 、springboot 、spring data jpa 集成

    项目地址:https://gitee.com/zhxs_code/PostgreSQL_springboot_jpa_demo.git 增删查改都已经实现. 重点部分: 1.定义自己的方言. pack ...

  3. python将数据库修改,数据库操作同步到数据库中

    *****************数据库迁移(同步)命令******************************** 1.python manage.py makemigrations 将数据库的 ...

  4. Linux 的目录结构

    原文内容来自于LZ(楼主)的印象笔记,如出现排版异常或图片丢失等问题,可查看当前链接:https://app.yinxiang.com/shard/s17/nl/19391737/cbbf47b0-f ...

  5. 全字段多条件搜索(api接口)

    近期在做项目时遇到了一个全表全字段多条件搜索的需求,在平时搜索最常见的就是 字段+like +‘% 条件%’这种模式,但遇到多条件多字段时,这种就不适用了. 表字段已知,条件未知,条件数量未知,这种情 ...

  6. Android设计模式—观察者模式

    装载请标明出处:https://www.cnblogs.com/tangZH/p/11175120.html  观察者模式 说白了,就是一个对发生改变,所有依赖于它的对象也发生改变,这是一对多的关系. ...

  7. Android 插件化开发(二):加载外部Dex文件

    在学习Java反射的技术后,我们可以开始更深一步的探究插件化开发了.首先先讲一下Android App的打包流程,然后我们通过一个简单的例子 —— 实现插件化加载外部Dex来完成初级的插件化开发的探索 ...

  8. Java分布式ID生成解决方案

    分布式ID生成器 我们采用的是开源的twitter(  非官方中文惯称:推特.是国外的一个网站,是一个社交网络及微博客服务)  的snowflake算法(推特雪花算法). 封装为工具类,源码如下: p ...

  9. Leetcode823 : 因子二叉树问题

    问题描述 给定一个数组,数组中的数不重复,且均大于1.要求使用数组中的数构建二叉树,每个数字可以被重复使用,除了叶子节点,每个节点的值等于其子节点的乘积,求构建二叉树的数量,返回的结果mod 10** ...

  10. ESP8266的RTOS版本ota在线升级基本流程及备忘

    ESP8266的ota升级由于涉及到不同的flash空间大小,以及新旧版本的不同,所以流程相对比较复杂.笔者这个倒腾的时间还是有一些的,不过,总归把事情解决了.下面记录一下基本的流程和遇到的问题. 还 ...