面向对象 - 继承与多态

本届需要讲述的内容不多,理解不困难(指自己复制粘贴跑一下都能懂,理解困难的都往后放了),就不那么逆天了

类的继承

定义

为提升代码复用性,可通过类的继承来快速写成功能相似的类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class haoHao{
public void fatherSay(){
System.out.println("I hava no money!");
}
}
class son extends haoHao{
public void sonSay(){
System.out.println("But my father has!");
}
}
public class sample{
public static void main(String[] args){
son zhangSan = new son();
zhangSan.fatherSay(); // 父类继承而来的方法
zhangSan.sonSay(); // 子类的独特方法
}
}

不像C++,Java只能继承一个类,后续会介绍进行多重继承时的情形。

重写

如果父类的方法不能满足子类的需求,那么就可以重写父类的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class haoHao{
public void fatherSay(){
System.out.println("I hava no money!");
}
}
class son extends haoHao{
@Override // 一种特殊的注释
public void fatherSay() {
System.out.println("No! My father never lacks of money!");
}
}
public class sample{
public static void main(String[] args){
son zhangSan = new son();
zhangSan.fatherSay(); // 输出的是子类重写后的结果
}
}

引用父类

继承并不是简单的并集关系,有时需要用super关键字来调用父类的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class haoHao{
public void fatherSay(){
System.out.println("I hava no money!");
}
}
class son extends haoHao{
public void sonSay() {
super.fatherSay();
fatherSay();
}
}
public class sample{
public static void main(String[] args){
son zhangSan = new son();
zhangSan.fatherSay();
zhangSan.sonSay();
}
}

多态

上溯造型

类的继承使子类拥有父类的所有变量与方法,发给父类的所有方法也能给子类使用,因此每一个子类都可以当作父类使用。因此Java允许创建不同类型对象的数组

1
2
3
4
5
6
7
8
9
10
11
12
class zhangHao{

}
class zhangSan extends zhangHao{

}
class zhangSi extends zhangHao{

}
class wangWu extends zhangHao{

}
1
2
3
4
zhangHao[] zhangHaoSon = new zhangHao[3];
zhangHaoSon[0] = new zhangSan();
zhangHaoSon[1] = new zhangSi();
zhangHaoSon[2] = new wangWu();

在不得不调用该对象数组时,编译器才会开始判断该对象元素的数据类型

重载

在一个类中,可以用多种参数定义同一个方法(包括构造方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class zhangHao{
public void printZhangHao(int age){
System.out.println("I'm " + age + " years old!");
}
public void printZhangHao(String name){
System.out.println("My name is " + name);
}
public void printZhangHao(boolean status, String name){
System.out.println("My love for " + name + " is " + status);
}
private void printZhangHao(double length){
System.out.println("I'm " + length + " at length");
}
}

像println方法一样,在调用方法的时候编译器会自动选择最适合的一种方法

Object类

更广泛的,所有的Java类都是Object类的子类,都可以使用或重写一些方法,如equals()/hashCode(), toString()等。而每个数据类型,每一个变量也都可以看作一个类(如Integer, String等),调用其中的equals(), toString()等方法。

应用

抽象类

既然Java可以实现多态,那么可以将多个相似的类的共性提取出来,合做一类,再在子类中声明其特性,而其原本的父类不需要创建实例。而这就是抽象类。抽象类不能创建类的实例对象,通过抽象类的接口处理类体系中的所有类。

1
2
3
4
5
6
7
8
9
10
11
12
abstract class zhangHao{

}
class zhangSan extends zhangHao{

}
class zhangSi extends zhangHao{

}
class wangWu extends zhangHao{

}
1
2
3
4
5
6
7
8
9
10
class sample{
public static void main(String[] args){
zhangHao[] zhangHaoSon = new zhangHao[3];
zhangHaoSon[0] = new zhangSan();
zhangHaoSon[1] = new zhangSi();
zhangHaoSon[2] = new wangWu();
new zhangHao(); // 报错
}
}
// 生的孩子有各种不一样,有可能完全不是自己的(大规模重写)

抽象类不能创造实例对象,但可以构造对象数组以存放子类

接口

接口是抽象类的进一步抽象,接口内只能进行方法的声明,具体方法的实现需要在对接的子类中写明。而且,接口也是一种类,也可以支持继承与多态。

1
2
3
4
5
6
7
8
9
10
11
12
// 如果前面不加default,方法后多打个大括号都是错
interface action{
void eat();
void sleep();
void daoGuan();
}
interface study{
void medicine();
void math();
void english();
void politics();
}

需要实现时,通过implements实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
abstract class zhangHao{
private int a = 1;
}
class zhangSan extends zhangHao implements action, study{ // 注意:extends必须放在implements前面
private int a = 1;

@Override
public void eat() {

}

@Override
public void sleep() {

}

@Override
public void daoGuan() {

}

@Override
public void medicine() {

}

@Override
public void math() {

}

@Override
public void english() {

}

@Override
public void politics() {

}
}
// 每一任孩子完成这些动作的具体细节是不一样的,需要另外声明。而继承表示若不重写则是一样的

在需要使用多重继承时,可以使用接口。接口可以进行多重实现,具体实现需要在实现的类中全部写明。
一般开发时,一个类通常继承于与自己关系最密切的抽象类中,而实现与其他有共同点的接口,再重写或再构造属于类自己的全部方法,最终完成类的全部定义。


面向对象 - 继承与多态
http://example.com/2024/04/24/object-oriented-2/
作者
Ivan Chen
发布于
2024年4月24日
许可协议
IVAN