第八章 多态

什么是多态

多态是对方法而言,同一种方法,但其实现的功能却不同(执行结果不同)

  • 多态的作用是清除类型间的耦合关系
  • 对同一种方法,传入参数类型不同,运行结果不同
  • 多态的实现依靠继承(向上转型)的特性
  • 多态又称动态绑定,后期绑定,运行时绑定

方法调用绑定

将一个方法调用同方法对象关联起来,根据关联时间,可分为两种:
动态绑定:程序运行时,根据对象类型进行绑定—-重点
‘静态绑定’:在程序执行前绑定

静态绑定的特点是:在程序运行前,就进行绑定
动态绑定特点是:编译器一直不知道对象类型,但是方法调用机制,能根据对象类型找到正确的方法体,即最终要调用哪种方法要看对象类型

向上转型+动态绑定 == 多态

一个多态的例子

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package package1;
interface Shape{
abstract void draw();
void erase();
int i=1;

}
//抽象方法可以是public,protected,默认包权限
//抽象类中的普通方法与其他普通方法相同
//接口类的方法,必须都是纯抽象方法,与抽象类不同的是:
//在接口类中无需显式的使用abstract定义抽象类,也可以显式定义
//接口类中方法默认权限都是public,可以设为static,abstract,其他的权限都不被允许
//接口类只能是public和abstract(可以从安全方面进行记忆)
//接口类的变量是常量,不可修改,故在定义常量时,必须给他赋值
abstract class Test{
void draw(){};
abstract void erase();
}

//对于继承接口的类而言,要重写接口类的所有方法,
//需要注意的是,这些接口类的方法是public类型
//因此,在重写的时候,也只能是public类型,不能降低权限

class Circle implements Shape{
public void draw(){
System.out.println("Circle`s draw");
}
public void erase(){
System.out.println("Circle`s erase");
}
}
class Square implements Shape{
public void draw(){
System.out.println("Square`s draw");
}
public void erase(){
System.out.println("Square`s erase");
}
}
public class demo1 implements Shape{
public void draw(){
System.out.println("demo`s draw");
}
public void erase(){
System.out.println("demo`s erase");
}
public static void main(String args[]){
Shape cirle = new Circle();
Shape square = new Square();
cirle.draw();
cirle.erase();
square.draw();
square.erase();
}

}

运行结果

1
2
3
4
Circle`s draw
Circle`s erase
Square`s draw
Square`s erase

多态的应用

利用多态机制,可以隐藏接口的实现–由于向上转型,所以无法确定是有哪种子类向上转型而来。
其次:可以将改变的事物与不变的事物分离开来,降低程序的耦合性,即,可以在不改变接口调用方法的情况下,修改接口的实现,而接口使用者无需了解接口如何实现,

域、静态与多态

域(field):A field is an attribute. A field may be a class’s variable, an object’s variable, an object’s method’s variable, or a parameter of a function.详细解析

域,静态方法是不具有多态性的。只有普通方法具有多态性

下面的例子是重点,需要重点理解!

接口类的多态性

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package Chapter9;

interface Shape{
abstract void draw();
void erase();
void getField();
String field="i am Shape`s field";
}

class Circle implements Shape{
String field =" i am Circle`s field";
public void getField(){
System.out.println("Cirle`s getField(): "+field);
}
public String getSupField(){
//return super.field;会报错
//获得接口中的域
return Shape.field;
}
public void draw(){
System.out.println("Circle`s draw");
}
public void erase(){
System.out.println("Circle`s erase");
}
}
class Square implements Shape{
String field =" i am Square`s field";
public void getField(){
System.out.println("Squsre`s getField(): "+field);
}
public void draw(){
System.out.println("Square`s draw");
}
public void erase(){
System.out.println("Square`s erase");
}
}
public class demo1 implements Shape{
String field =" i am Demo1`s field";
public void getField(){
System.out.println("demo`s getField(): "+field);
}
public void draw(){
System.out.println("demo`s draw");
}
public void erase(){
System.out.println("demo`s erase");
}
public static void main(String args[]){
Shape cirle = new Circle();
Shape square = new Square();
Shape demo = new demo1();
Circle c = new Circle();
cirle.draw();
cirle.erase();
cirle.getField();
System.out.println("获得接口中的域(getSupField) :"+c.getSupField());
System.out.println("Circle.field= "+cirle.field);
square.draw();
square.erase();
square.getField();
System.out.println("Square.field= "+cirle.field);
demo.getField();
System.out.println("Demo1.field= "+cirle.field);
}

}

运行结果

1
2
3
4
5
6
7
8
9
10
11
Circle`s draw
Circle`s erase
Cirle`s getField(): i am Circle`s field
获得接口中的域(getSupField) :i am Shape`s field
Circle.field= i am Shape`s field
Square`s draw
Square`s erase
Squsre`s getField(): i am Square`s field
Square.field= i am Shape`s field
demo`s getField(): i am Demo1`s field
Demo1.field= i am Shape`s field

分析

1
2
3
Shape cirle = new Circle();  //向上转型
cirle.getField(); // 结果为 i am Circle`s field
circle.field; // 结果为 i am Shape`s field

Circle类实现Shape接口,Circle和Shape都有field这个(变量),
当Circle向上转型成Shape时,获得field会出现何种情况?

  • 如果以调用接口类普通方法的形式,由于普通方法具有多态性,因此,field取决于对象中内部field的值
  • 如果不以方法形式获取,则就没有多态性,取决于引用的类型

继承形式的多态性

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package Chapter9;

//interface Shape{
// abstract void draw();
// void erase();
// void getField();
// String field="i am Shape`s field";
//}

class Shape{
String field="i am Shape`s field";
void draw(){};
void erase(){};
void getField(){};

}

class Circle extends Shape{
String field =" i am Circle`s field";
public void getField(){
System.out.println("Cirle`s getField(): "+field);
}
public String getSupField(){
//return super.field;若是实现接口,则会报错
return super.field;
}
public void draw(){
System.out.println("Circle`s draw");
}
public void erase(){
System.out.println("Circle`s erase");
}
}
class Square extends Shape{
String field =" i am Square`s field";
public void getField(){
System.out.println("Squsre`s getField(): "+field);
}
public void draw(){
System.out.println("Square`s draw");
}
public void erase(){
System.out.println("Square`s erase");
}
}
public class demo1 extends Shape{
String field =" i am Demo1`s field";
public void getField(){
System.out.println("demo`s getField(): "+field);
}
public void draw(){
System.out.println("demo`s draw");
}
public void erase(){
System.out.println("demo`s erase");
}
public static void main(String args[]){
Shape cirle = new Circle();
Shape square = new Square();
Shape demo = new demo1();
Circle c = new Circle();

cirle.getField();
System.out.println("获得基类中的域(getSupField) :"+c.getSupField());
System.out.println("Circle.field= "+cirle.field);

square.getField();
System.out.println("Square.field= "+cirle.field);
demo.getField();
System.out.println("Demo1.field= "+cirle.field);
}

}

运行结果

1
2
3
4
5
6
7
Cirle`s getField():      i am Circle`s field
获得基类中的域(getSupField) :i am Shape`s field
Circle.field= i am Shape`s field
Squsre`s getField(): i am Square`s field
Square.field= i am Shape`s field
demo`s getField(): i am Demo1`s field
Demo1.field= i am Shape`s field