做一个继承的例子,好吧......糟糕

时间:2014-10-15 23:14:31

标签: ruby inheritance

我正在阅读Ruby中的面向对象设计一书,其中有一部分将MountainBike类作为不良继承实践的一个例子。它没有完全显示,但暗示前者继承的Bicycle类以相同的方式编写。所以,我们的代码如下......

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 == :road
      { chain: '10-speed',
        tire_size: '23',
        tape_color: tape_color }
    else
      { chain: '10-speed',
        tire_size: '2.1',
        rear_shock: rear_shock }
    end
  end

end

class MountainBike < Bicycle
  attr_reader :front_shock, :rear_shock

  def initialize(args)
    @front_shock = args[:front_shock]
    @rear_shock = args[:rear_shock]
    super(args)
  end

  def spares
    super.merge(rear_shock: rear_shock)
  end
end

mountain_bike = MountainBike.new(
        size:        'S',
        front_shock: 'Manitou',
        rear_shock:  'Fox' )

puts mountain_bike.size
puts mountain_bike.spares

mountain_bike.spares的输出应该是这个争夺

{:tire_size => "23", :chain => "10-speed", :tape_color => nil, :front_shock => 'Manitou', :rear_shock => "Fox"}

但是,我得到的是

{:chain=>"10-speed", :tire_size=>"2.1", :rear_shock=>"Fox"}

显然没有证明预期的目的。 怎么可以重写班级自行车以匹配&#34;错误&#34;输出

2 个答案:

答案 0 :(得分:2)

我在这里看不出任何错误。

查看方法Bicycle {/ 1}}中的代码:

spares

您是否看到def spares if style == :road { chain: '10-speed', tire_size: '23', tape_color: tape_color } else { chain: '10-speed', tire_size: '2.1', rear_shock: rear_shock } end end 条件:if?对?好的,请在这里做一个说明。

现在,查看继承自if style == :road的类spares中的方法MountainBike

Bicycle

你看到def spares super.merge(rear_shock: rear_shock) end 了吗?它将调用父类的方法,在本例中为super方法。由于您使用以下函数初始化spares类的对象:

MountainBike

很明显,我们上面提到的条件将落在mountain_bike = MountainBike.new(size: 'S', front_shock: 'Manitou', rear_shock: 'Fox' ) # no style in argument!! 中,这将给出:

else

然后合并:

{ chain: '10-speed',
  tire_size: '2.1',
  rear_shock: rear_shock }

由于{ chain: '10-speed', tire_size: '2.1', rear_shock: rear_shock }.merge(rear_shock: rear_shock) 的值为rear_shock,因此上述代码将最终评估为:

'Fox'

难道你没想到的是什么?

请注意,{ chain: '10-speed', tire_size: '2.1', rear_shock: 'Fox' } 与撰写{a: 'b'}相同,它只是一种语法糖。

所以,我的观点是你读过的书中有一些不同的代码/方法来显示继承示例,或者它有一个错误打印的输出。它无法打印出来:

{:a => 'b'}

答案 1 :(得分:0)

Sivanes,你得到了错误的Bicycle课程。

在Ruby中的实用面向对象设计中,在第115页上,当引入上面的MountainBike类时,它说:

  

以下是MountainBike子类的第一次尝试。这个新的   子类是原始自行车类的直接后代。

原始Bicycle类是:

class Bicycle
  attr_reader :size, :tape_color

  def initialize(args)
    @size       = args[:size]
    @tape_color = args[:tape_color]
  end

  # every bike has the same defaults for
  # tire and chain size
  def spares
    { chain:        '10-speed',
      tire_size:    '23',
      tape_color:   tape_color}
  end

  # Many other methods...
end

使用此版本的Bicycle运行代码将为您提供正确的结果。