1 继承
1.1什么是继承:
继承
(inheritance)
机制
:是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特 性
的基础上进行
扩展,增加新功能
,这样产生新的类,称
派生类
。继承呈现了面向对象程序设计的层次结构, 体现了
由简单到复杂的认知过程。继承主要解决的问题是:
共性的抽取,实现代码复用
。
1.2怎么继承
在
Java
中如果要表示类之间的继承关系,需要借助
extends
关键字,具体如下:
修饰符
class
父类
{
// ...
}
修饰符
class
子类
extends
父类
{
// ...
}
比如:
// People.java
public class People{
String name
;
int
age
;
public
void
sleep
(){
System
.
out
.
println
(
name
+
"
正在睡觉
"
);
}
}
public class
Kid
extends
People
{
void
bark
(){
System
.
out
.
println
(
name
+
"
正在吃饭
"
);
}
}
// TestExtend.java
public class
TestExtend
{
public static
void
main
(
String
[]
args
) {
Kid kid
=
new
Kid
();
// kid类中并没有定义任何成员变量,
name
和
age属性肯定是从父类People中继承下来的
System
.
out
.
println
(
dog
.
name
);
System
.
out
.
println
(
dog
.
age
);
// kid访问
sleep()方法也是从People中继承下来的
dog
.
eat
();
dog
.
sleep
();
dog
.
bark
();
}
}
注意:
1.
子类会将父类中的成员变量或者成员方法继承到子类中了
2.
子类继承父类之后,必须要新添加自己特有的成员,体现出与基类的不同,否则就没有必要继承了
3.父类也被称为基类和超类,子类也被称为派生类
1.3 父类成员访问
子类可否直接访问父类继承下来的成员呢?
情况一:
子类和父类不存在同名成员变量
public class
Base
{
int
a
;
}
public class
Derived
extends
Base
{
int
b
;
public
void
method
(){
a
=
1
;
//
访问从父类中继承下来的
a
b
=
2
;
//
访问子类自己的b
}
}
情况二:
子类和父类成员变量同名
public class
Base
{
int
a
;
int
b
;
int
c
;
}
public class
Derived
extends
Base
{
int
a
;
//
与父类中成员
a
同名,且类型相同
char
b
;
//
与父类中成员
b
同名,但类型不同
public
void
method
(){
a
=
100
;
//
访问父类继承的
a
,还是子类自己新增的
a
?
b
=
101
;
//
访问父类继承的
b
,还是子类自己新增的
b?
c
=
102
;
//
子类没有
c
,访问的肯定是从父类继承下来的
c
// d = 103; // 编译失败,因为父类和子类都没有定义成员变量d
}
}
在子类方法中 或者 通过子类对象访问成员时
:
如果访问的成员变量子类中有,优先访问自己的成员变量。
如果访问的成员变量子类中无,则访问父类继承下来的,如果父类也没有定义,则编译报错。
如果访问的成员变量与父类中成员变量同名,则优先访问自己的。
成员变量访问遵循就近原则,自己有优先自己的,如果没有则向父类中找
。
情况三:
成员方法名字不同
public class
Base
{
public
void
methodA
(){
System
.
out
.
println
(
"Base
中的
methodA()"
);
}
}
public class
Derived
extends
Base
{
public
void
methodB
(){
System
.
out
.
println
(
"Derived
中的
methodB()
方法
"
);
}
public
void
methodC
(){
methodB
();
//
访问子类自己的
methodB()
methodA
();
//
访问父类继承的
methodA()
// methodD(); // 编译失败,在整个继承体系中没有发现方法
methodD()
}
}
成员方法没有同名时,在子类方法中或者通过子类对象访问方法时,则优先访问自己的,自己没有时 再到父类中找,如果父类中也没有则报错。
情况四:
成员方法名字相同
public class
Base
{
public
void
methodA
(){
System
.
out
.
println
(
"Base
中的
methodA()"
);
}
public
void
methodB
(){
System
.
out
.
println
(
"Base
中的
methodB()"
);
}
}
public class
Derived
extends
Base
{
public
void
methodA
(
int
a
) {
System
.
out
.
println
(
"Derived
中的
method(int)
方法
"
);
}
public
void
methodB
(){
System
.
out
.
println
(
"Derived
中的
methodB()
方法
"
);
}
public
void
methodC
(){
methodA
();
//
没有传参,访问父类中的
methodA()
methodA
(
20
);
//
传递
int
参数,访问子类中的
methodA(int)
methodB
();
//
直接访问,则永远访问到的都是子类中的
methodB()
,基类的无法访问到
}
}
通过子类对象访问父类与子类中不同名方法时,优先在子类中找,找到则访问,否则在父类中找,找到
则访问,否则编译报错。
通过派生类对象访问父类与子类同名方法时,如果父类和子类同名方法的参数列表不同
(
重载
)
,根据调用
方法适传递的参数选择合适的方法访问,如果没有则报错;、
问题:如果子类中存在与父类中相同的成员时,那如何在子类中访问父类相同名称的成员呢?
答:那么将会访问子类中的成员,进行
“重写”
(后续会细说)
1.4super关键字
作用:在子类方法中访问父类的成员。
class Base { public int a = 1; public int b = 2; } class Derived extends Base { public int a = 100; public int c = 3; public void test() { System.out.println(super.a); System.out.println(this.a); System.out.println(this.b); System.out.println(super.b); System.out.println(this.c); } } 结果为: 1 100 2 2 3 super访问父类对象,this优先访问子类,如果子类没有就去访问父类,如果父类也没有就会报错
1.5.子类构造方法
子类对象构造时,需要先调用基类构造方法,然后执行子类的构造方法。
public class
Base
{
public
Base
(){
System
.
out
.
println
(
"Base()"
);
}
}
public class
Derived
extends
Base
{
public
Derived
(){
System
.
out
.
println
(
"Derived()"
);
}
}
public class
Test
{
public static
void
main
(
String
[]
args
) {
Derived d
=
new
Derived
();
}
}
结果打印:
Base
()
Derived
()
1.6.super和this
【
相同点
】
1.
都是
Java
中的关键字
2.
只能在类的非静态方法中使用,用来访问非静态成员方法和字段
3.
在构造方法中调用时,必须是构造方法中的第一条语句,并且不能同时存在
【
不同点
】
1. this
是当前对象的引用,当前对象即调用实例方法的对象,
super
相当于是子类对象中从父类继承下来部分成员的引用。
1.7final
修饰变量或字段,表示常量
(
即不能修改,与C语言中的const类似
)
final
int
a
=
10
;
a
=
20
;
//
编译出错