0%

Inheritance

What is inheritance ?

  1. 继承的核心是 实现消息的自动委托

重构

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
class 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
  1. 找出抽象:子类是其父类的特殊化。子类应该包含父类的一切内容,外加更多内容。任何期待父类的对象应该都能够与其子类进行交互。
  2. 创建抽象父类先将所有的代码下放到子类然后逐渐地、部分地提升是重构操作的重要组成部分。因为一开始只将部分行为下放到子类,然后试图将某个现有的类从具体转换为抽象,那么有可能会不小心残留下具体的行为。
    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
    class 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

  3. 提升抽象行为
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    class 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
  4. 使用模板方法模式 在负类定义好几本结构,并通过发送消息来获取子类特有的实现,这种方法称为模板方法模式。使用模板方法模式的类都必须给它所发送的每一条消息提供一个实现。
    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
    class 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
  5. 管理父类和子类之间的耦合 一如既往,当知道其他类相关的事情,变回创建依赖关系。发送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
    57
    class 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