Java--继承
前言
几个月不看就又忘了,看了一遍顺便记录一下。
关于继承
简而言之,继承主要解决的问题就是:共性抽取
代码定义:
-
父类:也称作基类、超类
1
2
3public class 父类名称 {
// ...
} -
子类:也称作派生类
1
2
3public class 子类名称 extends 父类名称 {
// ...
}
最高父类其实就是一个普通类,这点在代码定义时就可以看出来;
在继承的关系中,“子类就是一个父类”。也就是说,子类可以被当做父类看待。(例如:父类是员工,其子类有经理、业务员。那么可以有这样的表达:“经理、业务员是员工”)
在继承关系中:
-
子类可以拥有父类的“内容”
-
子类还可以定义除父类之外的专有内容
-
Java语言是单继承的:一个类的直接父类只能有唯一一个
-
Java语言可以多级继承:
1
2
3class A {}
Class B extends A {}
class C extends B {} -
一个父类可以拥有很多个子类:
1
2
3class A {}
class B extends A {}
class C extends A {}
用法
基本使用
定义父类Fu
:
1 | public class Fu { |
定义子类Zi
:
1 | public class Zi extends Fu{ |
使用类Demo
:
1 | public class Demo { |
运行结果:
1 | 这是父类变量 |
成员变量访问
- 局部变量:
局部变量名
- 本类的成员变量:
this.成员变量名
- 父类的成员变量:
super.成员变量名
定义父类Fu
:
1 | public class Fu { |
定义子类Zi
:
1 | public class Zi extends Fu{ |
使用类Demo
:
1 | public class Demo { |
运行结果:
1 | 局部变量 |
成员方法访问
基本使用
访问规则:创建的对象是谁,就优先用谁的方法,如果没有,则向上找父类。
重写
在继承关系当中,方法名称一样,参数列表也一样。
注意区别重写与重载:
- 重写(Override):方法的名称一样,参数列表也一样。
- 重载(Overload):方法的名称一样,参数列表不一样。
注解@Override
:写在方法前面,用来检测是不是有效的正确重写。(也可以不写。建议书写,起到检测作用)
定义父类Fu
:
1 | public class Fu { |
定义子类Zi
:
1 | public class Zi extends Fu{ |
使用类Demo
:
1 | public class Demo { |
运行结果:
1 | 子类重名方法执行 |
在继承关系中定义方法需要注意:
-
子类方法的返回值必须小于等于父类方法的返回值范围
java.lang.Object类
是所有类的公共最高父类,而java.lang.String类
就是Object的子类 -
子类方法的权限必须大于等于父类方法的权限修饰符
public > protected > (default) > private
(注:(default)不是关键字default,而是什么都不写,留空)
构造方法访问
基本使用
继承关系中,父子类构造方法的访问特点:
- 子类构造方法当中有一个默认隐含的
super();
调用,所以一定是先调用的父类构造方法,后执行的子类构造方法 - 子类构造方法可以通过super关键字来调用父类重载构造方法
- super的父类构造调用,必须是子类构造方法的第一个语句。(不能一个子类构造调用多次super构造)
定义父类Fu
:
1 | public class Fu { |
定义子类Zi
:
1 | public class Zi extends Fu{ |
使用类Demo
:
1 | public class Demo { |
运行结果:
1 | 父类无参构造方法 |
Super
用法:
- 在子类的成员方法中,访问父类的成员变量
- 在子类的成员方法中,访问父类的成员方法
- 在子类的构造方法中,访问父类的构造方法
定义父类Fu
:
1 | public class Fu { |
定义子类Zi
:
1 | public class Zi extends Fu{ |
使用类Demo
:
1 | public class Demo { |
运行结果:
1 | 父类有参构造方法 |
this
用法:
- 在本类的成员方法中,访问本类的成员变量
- 在本类的成员方法中,访问本类的另一个成员方法
- 在本类的构造方法中,访问本类的另一个构造方法
注意:
this(...)
调用也必须是构造方法的第一个语句,且是唯一一个super(...)
和this(...)
两种构造调用,不能同时使用
Demo
:
1 | public class Demo { |
运行结果:
1 | 全参构造方法 |
抽象(abstract)
如果父类中的方法不确定如何具体实现方法体的内容,那么就应该考虑使用抽象方法。
例如:父类为
Animal
,其有两个子类Dog
、Cat
。在Animal
父类中定义了一个Eat(...){...}
的方法,但是由于狗啃骨头、猫吃鱼,这两个子类的吃行为是不一样的,无法在父类的方法体中进行准确定义,这时就需要将Eat(...)
定义为抽象方法。
概念:
-
抽象方法:用abstract关键字修饰,然后去掉方法体,直接分号结束
public abstract void method(...);
-
抽象类:抽象方法所在的类,必须是抽象类才行。在class之前用abstract关键字修饰
使用时需要注意:
- 不能直接new抽象类对象
- 必须用一个子类来继承抽象父类
- 子类必须覆盖重写抽象父类当中所有的抽象方法,否则该子类也必须为抽象类
- 抽象类需要创建子类对象进行使用
- 一个抽象类不一定含有抽象方法,只要保证抽象方法所在的类是抽象类即可(在一些特殊场景下有用途)
定义抽象父类Fu
:
1 | public abstract class Fu { |
定义子类Zi
:
1 | public class Zi extends Fu { |
使用类Demo
:
1 | public class Demo { |
运行结果:
1
重写父类的抽象方法
1 | 重写父类的抽象方法 |
后记
无