一.继承的引入(为什么要继承)
1.1引入
我们举一个很常见的例子,在进入社会之前,我相信很多人都有过学生的经历,那么我们身为学生大概都会就会经历小学、初中、高中、大学、研究生、博士生......
每个阶段都有考试,我们的成绩单都会对应自己姓名加成绩,那么我要写一个程序打出我从小学到博士生毕业成绩,显然这其中会有很多的重复代码,那么我们为什么不可以把重复的写到一个类中,然后再各自调用呢,这样看起来就方便很多,于是引出继承。
继承可以
解决代码复用
,
让我们的编程更加靠近人类思维
.
当多个类存在
相同的属性(变量)和方法时
,
可以从这些类中
抽象出父类
,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过
extends 来声明继承
父类即可。
1.2示意图
示意图中父子类是相对关系,B可以说是D的父类,也可以说是A的子类。
1.3继承基本语法
class 子类 extends 父类{}
子类就会自动拥有父类定义的属性和方法;
父类又叫超类、基类;
子类又叫派生类;
1.4继承给编程带来的便利
1)
代码的复用性提高了
2)
代码的扩展性和维护性提高了
二.继承的深入讨论/细节问题(10条)
2.1继承访问限制
1)子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问
,
但是私有属性和方法不能在子类直接访问,要通过父类提供公共的方法去访问。
准备工作,我们创建基类Base,子类Sub进行测试
public class Base {
public int n1 = 10;
protected int n2 = 20;
int n3 = 30;
private int n4 = 40;
public Base(){
System.out.println("父类 Base()构造器被调用....");
}
public void test10(){
System.out.println("test10");
}
protected void test20(){
System.out.println("test20");
}
void test30(){
System.out.println("test30");
}
private void test40(){
System.out.println("test40");
}
}
public class Sub extends Base{
public Sub() {
System.out.println("子类 Sub()构造器被调用....");
}
}
我们可以看到,private是不允许被调用的,我们可以使用get方法声明一个公开的来调用(在基类中)
public void getN4() {
System.out.println(n4);
}
那么我们就可以通过调用getN4来输出n4的值了。
2.2super引入
2)子类必须调用父类的构造器, 完成父类的初始化
3)
当创建子类对象时,不管使用子类的哪个构造器,
默认情况下总会去调用父类的无参构造器
,如果父类没有提供无 参构造器,则必须在子类的构造器中用 super 去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过(怎么理解。) [举例说明]
4)
如果希望指定去调用父类的某个构造器,则显式的调用一下
: super(
参数列表
)
5) super
在使用时,必须放在构造器第一行
(super
只能在构造器中使用
)
6) super()
和
this()
都只能放在构造器第一行,因此这两个方法不能共存在一个构造器
public class Base {
public int n1 = 10;
protected int n2 = 20;
int n3 = 30;
private int n4 = 40;
public Base(){
System.out.println("父类 Base()构造器被调用....");
}
public Base(int n1, int n2) {
this.n1 = n1;
this.n2 = n2;
System.out.println("父类 Base(int n1, int n2)构造器被调用....");
}
基类中有两个构造器
public class Sub extends Base{
public Sub() {
System.out.println("子类 Sub()构造器被调用....");
}
}
子类中一个无参构造器
public class ExtendsTest {
public static void main(String[] args) {
Sub sub = new Sub();
}
}
创建对象,会完成父类的初始化,但是我们看运行结果,发现,它打印的是基类中的无参方法,这里其实在Sub构造器中隐藏了super,没有指定时候,它会默认指定为基类中的无参构造器。
指定特定构造器看结果
7) java
所有类都是
Object
类的子类
, Object
是所有类的基类
.
8)
父类构造器的调用不限于直接父类!将一直往上追溯直到
Object
类
(
顶级父类
)
9)
子类最多只能继承一个父类
(
指直接继承
)
,即
java
中是单继承机制。 思考:如何让 A
类继承
B
类和
C
类? 【
A
继承
B
,
B
继承
C
】
10)
不能滥用继承,子类和父类之间必须满足
is-a 的逻辑关系(例如猫类不可以继承汽车类)
三.继承本质
当子类对象创建好后,建立查找关系
(1)
首先看子类是否有该属性
(2)
如果子类有这个属性,并且可以访问,则返回信息
(3)
如果子类没有这个属性,就看父类有没有这个属性
(
如果父类有该属性,并且可以访问,就返回信息
..)
(4)
如果父类没有就按照
(3)
的规则,继续找上级父类,直到
Object..
3.1案例详析
public class ExtendsTheory {
public static void main(String[] args) {
Son son = new Son();
System.out.println(son.name);//返回的是儿子的name
son.age;//不会继续往爷爷哪里找,爸爸私有,就会堵在这里
}
}
class GrangPa {
String name = "大头爷爷";
String hobby = "旅游";
}
class Father extends GrangPa {
String name = "大头爸爸";
private int age = 80;
}
class Son extends Father {
String name = "大头儿子";
}
我们的age是私有的,访问受限,报错;
3.2分析图
四.用到的快捷键
ctrl+b 追溯
ctrl+h 继承图