Java中的多态,多态时面向对象的灵魂,是最重要的特性
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
|
public class Main {
public class Base {
public void sayHello() {
System.out.println("Hello");
}
}
public class Sub extends Base {
@Override
public void sayHello() {
System.out.println("你好");
}
}
public static void main(String[] args) {
/*
虽然你用的是父类类型变量,但它实际是子类类型的对象
因此this等于Sub类型的对象,因此实际调用的是sub对象的sayHello方法
这就是面向对象的多态性
几个例子,例如HashSet.addAll方法,由于HashSet本身并没有addAll方法
因此它调用的是它父类的addAll方法,在父类的addAll方法中,又调用了add(这一点
可以跟踪HashSet源码看到),那么到这里你肯定会觉得它调用的是父类自己的add方法,
但其实调用的是HashSet的add方法,因为this是HashSet
还比如你可能经常见到这种用法:
List list = new ArrayList(); 这些都是用到了多态的特性
*/
Base base = new Sub();
base.sayHello();
}
}
|
- 在运行时根据
this
是谁,来决定调用谁的方法
- 实例方法默认是多态的
- 静态方法没有多态特性
- 参数也没有多态特性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
public class Main {
/**
* 有这么一个需求,给定一个产品的名字,返回它的价格
* 下面的实现方式有什么弊端? 如何优化?
* @param name 产品名
* @return 返回这个产品的价格
*/
public static int getPrice(String name) {
/*
这个实现不好,因为未来每加一个产品,你都需要添加一个case语句,
这样会造成你的代码又臭又长,我们可以通过策略模式来解决它
*/
switch (name) {
case "MacBook":
return 14999;
case "iPhone":
return 8999;
default:
return 0;
}
}
}
|
我们可以抽取共性,将返回价格的策略提取成一个类,这个例子策略就是产品名字,我们通过产品名来返回相应的价格
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
|
/**
* 产品类,基类,它有一个返回产品价格的方法
* 实际上这个可以换成接口,不过现在还没学到接口,以后再说了
*/
public class Product {
/**
* @return 返回这个产品的价格
*/
public int discount() {
return 0;
}
}
/**
* MacBook类,它继承了产品类,并重写了discount方法,用于返回MacBook自己的价格
*/
public class MacBook extends Product {
private static final int PRICE = 14999;
@Override
public int discount() {
return PRICE;
}
}
/**
* iPhone类,它继承了产品类,并重写了discount方法,用于返回iPhone自己的价格
*/
public class IPhone extends Product {
private static final int PRICE = 8999;
@Override
public int discount() {
return PRICE;
}
}
public class Main {
/**
* 这里就利用了多态性来实现策略的分发
* 虽然这里的参数是Product类型,但由于向上转型可知,我们可以传递子类对象进来
* 又因为多态性,this指向的是子类对象,所以调用的是子类的discount方法
* @param product 产品类
* @return 返回这个产品的价格
*/
public static int getPrice(Product product) {
return product.discount();
}
public static void main(String[] args) {
System.out.println(getPrice(new MacBook()));
System.out.println(getPrice(new IPhone()));
}
}
|
- 涉及金额的时候,绝对不可以用
double
因为double
是不精确的,它是一个近似值而不是绝对值
- 你应该使用
BigDecimal
类型,因为它是精确的