What is inheritance ?
- 继承的核心是
实现消息的自动委托
。
重构
1 | class Bicycle |
- 找出抽象:子类是其父类的特殊化。子类应该包含父类的一切内容,外加更多内容。任何期待父类的对象应该都能够与其子类进行交互。
- 创建抽象父类先将所有的代码下放到子类然后逐渐地、部分地提升是重构操作的重要组成部分。因为一开始只将部分行为下放到子类,然后试图将某个现有的类从具体转换为抽象,那么有可能会不小心残留下具体的行为。
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
36class Bicycle
# 这个类为空
# 所有的代码都移动到了 RoadBike
end
class RoadBike < Bicycle
attr_reader :style,:size,:tape_color,:front_shock,:rear_shock
def initialize(args)
@style = args[:style]
@size = args[:size]
@tape_color = args[:tape_color]
@front_shock = args[:front_shock]
@rear_shock = args[:rear_shock]
end
def spares
if style == :read
{
chain: '10-speed',
tire_size: '23',
}
else
{
chain: '10-speed',
tire_size: '2.1',
rear_shock: rear_shock
}
end
end
end
class Mountain < Bicycle
end - 提升抽象行为
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24class Bicycle
attr_reader :size
def initialize(args = {})
@size = args[:size]
end
end
class RoadBike < Bicycle
attr_reader :tape_color
def initialize(args)
@tape_color = args[:tape_color]
super(args)
end
# ......
end
class Mountain < Bicycle
# ......
end - 使用模板方法模式 在负类定义好几本结构,并通过发送消息来获取子类特有的实现,这种方法称为
模板方法模式
。使用模板方法模式的类都必须给它所发送的每一条消息提供一个实现。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
35class Bicycle
attr_reader :size,:chain,:tire_size
def initialize(args = {})
@size = args[:size]
@chain = args[:chain] || default_chain
@tire_size = args[:tire_size] || default_tire_size
end
def default_chain
'10-speed'
end
def default_tire_size
raise NotImplememtedError
end
end
class RoadBike < Bicycle
attr_reader :tape_color
def initialize(args)
@tape_color = args[:tape_color]
super(args)
end
def default_chain
'9-speed'
end
end
class Mountain < Bicycle
# ......
end - 管理父类和子类之间的耦合 一如既往,当知道其他类相关的事情,变回创建依赖关系。发送
super
消息的子类,不仅需要知道自己在干什么,还需要知道自己与父类是如何交互的。可以使用钩子消息解耦子类。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
57class Bicycle
attr_reader :size,:chain,:tire_size
def initialize(args = {})
@size = args[:size]
@chain = args[:chain] || default_chain
@tire_size = args[:tire_size] || default_tire_size
post_initialize(args)
end
def spares
{tire_size: tire_size,
chain: chain}.mege(local_spares)
end
def local_spares
{}
end
def post_initialize(args)
nil
end
def default_chain
'10-speed'
end
def default_tire_size
raise NotImplememtedError
end
end
class RoadBike < Bicycle
attr_reader :tape_color
def post_initialize(args)
@tape_color = args[:tape_color]
end
def local_spares
{tape_color: tape_color}
end
def default_tire_size
'23'
end
end
class Mountain < Bicycle
# ......
end