我正在阅读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;输出
答案 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
运行代码将为您提供正确的结果。