Java之——“继承”

前言

在了解完类和对象之后,想必大家对Java又有了新的认识,今天我们来介绍继承,接下来的学习我们将步入Java语法阶段的重点和难点,加油宝儿们!!!



继承

1.为什么需要继承

  • Java中使用类对现实世界中实体来进行描述,类经过实例化之后的产物对象,则可以用来表示现实中的实体,但是现实世界错综复杂,事物之间可能会存在一些关联,那么在设计程序中就需要进行考虑如何将代码进行简化呢?
    在这里插入图片描述
  • 比如:猫和狗,它们都是动物,我们可以把它们共有的属性、方法拿出来——这就叫继承。接下来,我会带你们细细分析“继承”

2.继承的概念

能否对猫和狗的共性进行抽取呢?面向对象思想中提出了继承的概念,专门用来进行共性抽取,实现代码复用
继承机制:是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行拓展,增加新功能,这样产生新的类,称为派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程,继承主要解决的问题是:共性的抽取,实现代码复用
例如:猫和狗都是动物,那么我们就可以将共性的内容进行抽取,然后采用继承的思想来达到共用。

画图理解如下

在这里插入图片描述

3.继承的语法

在Java中如果要表示类之间的继承关系,需要借助extends关键字

修饰符 class 子类 extends 父类{
……
}
在这里插入图片描述

对上述场景用代码实现

class Animal{
    String name;   int age;    String sex;
    public void greet(){
        System.out.println(name+"大家好!!!");
    }
    public void sleep(){
        System.out.println(name+"在睡觉!!!");
    }
    public void drink(){
        System.out.println(name+"在喝水!!!");
    }
}
class Cat extends Animal{
    public void eat(){
        System.out.println(name+"吃猫粮!!!");
    }
}
class Dog extends Animal{
    public void eat(){
        System.out.println(name+"吃狗粮!!!");
    }
}

上述图示中,Dog和Cat都继承里Animal类,其中Animal类称为父类(基类或超类),Dog和Cat可以成为Animal的子类(派生类),继承之后。子类可以复用父类中的成员,子类在实现时只需关心自己新增加的成员即可。
继承成员方法和成员变量,达到了代码复用的效果

4.父类成员访问(重点!!!)

在继承体系中,子类将父类中的方法和字段继承下来了,那在子类中能否直接访问父类中继承下来的成员呢?

(1)子类和父类不存在同名成员变量

子类和父类不存在同名成员变量时,只需要extends关键字就可以在子类中直接访问

代码如下

class Base{
    int a;
    int b;
}
class Derived extends Base{
    int c;
    public void method(){
        a = 10;//访问从父类中继承下来的a
        b = 20;//访问从父类中继承下来的b
        c = 30;//访问自己子类的c
    }
}

(2)子类和父类成员变量同名!!!

引入super关键字

由于设计不好或者因场景需要,子类和父类中可能会存在相同名称的成员,如果要在子类方法中访问父类同名成员时,该如何操作?直接访问是无法做到的Java提供了super关键字,该关键字的作用:在子类方法中访问父类的成员。

理解superthis的区别!!!

1.当子类和父类是同名的成员变量时在子类当中访问这个同名的成员变量,访问的是子类自己的
2.this既可以访问父类的成员变量,也可以访问子类的成员变量,this访问父子同名变量时遵循子类优先
3.super只能访问从父类中继承过来的成员变量
4.super只是一个关键字,提高代码的可读性,让别人看到这样访问就知道访问的是父类

画图理解superthis的效果

在这里插入图片描述

代码理解(访问成员变量)

class Base{
    int a;  String b;
}
class Derived extends Base{
    int a;  String b;  int c;
    public void method(){
        super.a = 10;//访问从父类中继承下来的a
        this.a = 20;//访问子类中的a,等价于a = 20;
        super.b = "abc";//访问从父类中继承下来的b
        this.b = "def";//访问子类中的b ,等价于b = "def";
        c = 30;//访问自己子类的c
    }
}

代码理解(访问成员方法)

class text{
    public void fun(){
        System.out.println("打印父类的成员方法");
    }
}
class text2 extends text{
  public void fun(){
        System.out.println("打印子类的成员方法");
        super.fun();
    }
}
public class text1 {
    public static void main(String[] args) {
        text2 text = new text2();
        text.fun();
    }
}
//输出结果///
打印子类的成员方法
打印父类的成员方法

Process finished with exit code 0

【说明】

  • 通过子类对象访问父类与子类中不同名方法时,优先在子类中找,找到则访问,否则在父类中找,找到则访问,否则编译报错
  • 通过派生类对象访问父类与子类同名方法时,如果父类和子类同名方法的参数列表不同(重载),根据调用方法适传递的参数选择合适的方法访问,如果没有则报错

super.data 访问父类成员变量
super.fun() 访问父类成员方法
super() 访问父类构造方法

5.子类构造方法

父子父子,先有父后有子
当子类继承父类后,要先帮助父类(只能在子类中调用父类的构造方法)进行构造,然后在构造自己

代码理解

class Method{
    public Method(){
        System.out.println("打印父类的构造方法");
    }
}
class Met extends Method{
    public Met(){
        //super();
        //注意子类构造方法中默认会调用父类的无参构造方法
        //用户没有写时,编译器会自动增加,而且super()必须是子类构造的第一条语句
        System.out.println("打印子类的构造方法");
    }
}
public class lyn1 {
    public static void main(String[] args) {
        Met met = new Met();
    }
}
///输出结果//
打印父类的构造方法
打印子类的构造方法

Process finished with exit code 0

【注意】

  • 若父类显式定义无参或默认的构造方法,在子类构造方法第一行默认有隐含的super()语句,即调用父类构造方法
  • 如果父类构造方法是带有参数的,此时需要用户为子类显式定义构造方法,并在子类构造方法中选择合适的父类构造方法调用,否则编译失败
  • 在子类构造方法中,super()调用父类构造时,必须是子类构造函数中的第一条语句
  • super()只能在子类构造方法中出现一次,并且不能和this同时出现,因为二者都必须是构造方法中的第一条语句,并且不能同时存在

6.继承关系上的执行顺序

代码理解

class Person{
    public Person(){
        System.out.println("Person构造方法执行");
    }
    {
        System.out.println("Person实例代码块执行");
    }
    static {
        System.out.println("Person静态代码块执行");
    }
}
class Student extends Person{
    public Student(){
        System.out.println("Student构造方法执行");
    }
    {
        System.out.println("Student实例代码块执行");
    }
    static {
        System.out.println("Student静态代码块执行");
    }
}
public class lynnn {
    public static void main(String[] args) {
        Person person = new Person();
        System.out.println("==================");
        Student student = new Student();
    }
}
///输出结果
Person静态代码块执行
Person实例代码块执行
Person构造方法执行
==================
Student静态代码块执行
Person实例代码块执行
Person构造方法执行
Student实例代码块执行
Student构造方法执行

Process finished with exit code 0

通过分析执行结果,得出以下结论:

  1. 父类静态代码块优先于子类静态代码块执行,且是最早执行
  2. 父类实例代码块父类构造方法紧接着执行
  3. 子类实例代码块子类构造方法紧接着再执行
  4. 静态代码块只执行一次

7.Java中支持的继承方式总结

单继承

Alt

class A{
    /
}
class B extends A{
    /
}

多层继承

Alt

class A{//......}
class B extends A{//......}
class C extends B{//......}

不同类继承同一个类

Alt

class A{//......}
class B extends A{//......}
class C extends A{//......}

8.final关键字

final关键字可以来修饰变量、成员方法以及类,一个类不想被继承时,使用关键字final

用来修饰变量或字段,表示常量(不能被修改)

final int a = 10;
a =  20;//编译出错

修饰类:表示此类不能被继承

final class Animal{
    ///......
}
class Bird extends Animal{
    ///...
}//编译出错

9.继承与组合

和继承类似,组合也是一种表达类之间关系的方式,也是能够达到代码重用的效果。组合并没有涉及到特殊的语法,仅仅是将一个类的实例作为另一个类的字段

继承表示对象之间是is-a的关系,比如:狗是动物,猫是动物
组合表示对象之间是has-a(a part of)的关系,比如:汽车和发动机,方向盘,轮胎等关系就应该是组合,因为汽车是由这些部件组成的

代码理解

//轮胎类
class Tire{
    /
}
//发动机类
class Engine{
    
}
class Car{
    private Tire tire;//可以复用轮胎中的属性和方法
    private Engine engine;//可以复用发动机中的属性和方法
}
//奔驰是汽车
class Benz extends Car{
    //将汽车中包含的轮胎,发动机等全部继承下来
}

组合和继承都可以实现代码复用,应该使用组合还是继承,需要根据应用场景来选择,一般建议:能用组合尽量使用组合。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值