继承(Inheritance)


文章目录

  • 继承(Inheritance)
  • 概念
  • 基本语法
  • 继承的细节事项
  • super关键字
  • 使用细节
  • 方法重写/覆盖(Override)
  • 使用细节
  • 重载和重写的异同


概念

编写Java项目时,一个项目里时常会有多个具有相同属性或相同方法的类,此时抽象出一个类,即从这些类中将相同的属性或方法放在一个类中,这个类称为父类(基类、超类)。其余的类只需通过关键字extends声明继承父类的属性和方法即可。

基本语法

class ParentName{
	field;//属性
    method;//成员方法
}

class SubclassesName1 extends ParentName{
	//此时子类会继承父类的属性和方法
}

class SubclassesName2 extends SubclassesName1{
	//此时ParentName类也可以视为SubclassesName2类的父类
}
  • 子类又可叫派生类,父类和子类关系是相互的

继承的细节事项

1.子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问,但是私有属性和方法不能在子类直接访问,要通过父类提供的公共的方法去访问

2.子类必须调用父类的构造器,完成父类的初始化

class Parent {
    String name;

    public Parent() {
        this.name = "父类";
        System.out.println("父类构造器运行");
    }

    void print1(){
        System.out.println(this.name);
    }
}

class Subclasses extends Parent{
    String name;

    public Subclasses() {
        //此时子类构造首行隐藏了一句super(); 
        //该语句会调用父类的构造器
        this.name = "子类";
        System.out.println("子类构造器运行");
    }

    @Override
    void print1() {
        super.print1();
    }

    void print2(){
        System.out.println(this.name);
    }
}

public class Test{
    public static void main(String[] args) {
        Subclasses subclasses = new Subclasses();
        subclasses.print1();
        subclasses.print2();
    }
}
//运行结果
父类构造器运行
子类构造器运行
父类
子类

从运行结果可见,即使没有实例化父类的对象,在实例化子类对象时仍会先调用父类的构造器完成对父类的初始化再调用子类的构造器完成对子类的初始化

当创建子类对象时,不管使用子类哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用super去指定使用父类的哪个构造器完成对父类的初始工作

如果希望指定去调用父类的某个构造器,则显式的调用一下: super (参数列表)

3.Java所有类都是Object的子类,Object是所有类的基类,父类构造器的调用不限于直接父类,将一直往上追溯直到Object类

4.子类最多只能直接继承一个父类,即Java是单继承机制

5.不能滥用继承,子类和父类间必须满足 is - a 的逻辑关系,编写代码时最好不要超过两次继承
如:Animal的子类为Dog,满足狗是动物的逻辑关系

6.子类会按照查找关系来返回信息

1)首先看子类是否有该属性(方法也是如此)

2)如果子类有这个属性,并且可以访问,则返回信息

3)如果子类没有这个属性,就看父类有没有这个属性(如果父类有该属性,并且可以访问,就返回信息)

4)如果父类没有就按照(3)的规则,继续找上级父类,直到Object类

super关键字

  • 访问父类的属性、方法、构造器,但不能访问private修饰的成员
  • 在构造器中只能出现一句且不能与this共存,因为两者都需放在首句

super和this的比较

序号

区别

this

super

1

访问属性

访问本类属性,如果本类没有此属性则从父类中继续查找

直接从父类开始查找

2

调用方法

访问本类中的方法,如果本类没有此方法则从父类中继续查找

直接从父类开始查找

3

调用构造器

调用本类构造器,必须放在构造器的首行

调用父类构造器,必须放在子类构造器的首行

4

特殊

表示当前对象

子类中访问父类对象

使用细节

super.属性or方法名;

效果:直接跳过本类查找父类中的方法

super的访问不限于直接父类,如果多个基类(上级类)中都有同名的成员,使用super访问遵循就近原则

方法重写/覆盖(Override)

基本概念:子类有一个方法与父类的某个方法的名称、返回类型、参数一样

使用细节

  • 子类的方法的参数,方法名称,要和父类完全一致
  • 子类方法的返回类型也需和父类返回类型一样,或者是父类返回类型的子类
public Object getInfo () {}//父类方法
public String getInfo () {}//子类方法
  • 子类方法不能缩小父类方法的访问权限,但能扩大

如:父类方法用的是public修饰,但子类用了protected

重载和重写的异同

名称

发生范围

方法名

形参列表

返回类型

修饰符

重载(Overload)

本类

相同

类型,个数或顺序至少有一个不同

无要求

无要求

重写(Override)

父子类

相同

相同

相同或子类的返回类型为父类返回类型的子类

子类方法不能缩小父类方法的访问