Ruby 2.1:组成一辆由零件组成的自行车->为nil:NilClass(NoMethodError)调用了私有方法'select'
运行此代码时出现错误。以下是输出:Ruby 2.1:组成一辆由零件组成的自行车->为nil:NilClass(NoMethodError)调用了私有方法'select',ruby,oop,conventions,Ruby,Oop,Conventions,运行此代码时出现错误。以下是输出: L Bicycle#Ex3.rb:32:in `spares': private method `select' called for nil:NilClass (NoMethodError) from Bicycle#Ex3.rb:10:in `spares' from Bicycle#Ex3.rb:111:in `<main>' 代码如下: class Bicycle attr_reader :size, :parts
L
Bicycle#Ex3.rb:32:in `spares': private method `select' called for nil:NilClass (NoMethodError)
from Bicycle#Ex3.rb:10:in `spares'
from Bicycle#Ex3.rb:111:in `<main>'
代码如下:
class Bicycle
attr_reader :size, :parts
def initialize(args={})
@size = args[:size]
@parts = args[:parts]
end
def spares
parts.spares # return an array
end
def lead_days
1
end
#...
end
class Parts
attr_reader :parts
def initialize(args={})
@parts = parts
end
def size
parts.size
end
def spares
parts.select{|part| part.needs_spare}
end
end
class Part
attr_reader :name, :description, :needs_spare
def initialize(args)
@name = args[:name]
@description = args[:description]
@needs_spare = args.fetch(:needs_spare, true)
end
end
class RoadBikeParts < Parts
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 MountainBikeParts < Parts
attr_reader :front_shock, :rear_shock
def post_initialize(args)
@front_shock = args[:front_shock]
@rear_shock = args[:rear_shock]
end
def local_spares
{ rear_shock: rear_shock}
end
def default_tire_size
'2.1'
end
end
chain = Part.new(
name: 'chain',
description: '10 speed')
road_tire = Part.new(
name: 'tape_size',
description: '23')
tape = Part.new(
name: 'tape_color',
description: 'red')
mountain_tire = Part.new(
name: 'tire_size',
description: '2.1')
rear_shock = Part.new(
name: 'rear_shock',
description: 'Fox')
front_shock = Part.new(
name: 'front_shock',
description: 'Manitou',
needs_spare: false)
road_bike_part = Parts.new([chain, road_tire, tape])
road_bike = Bicycle.new(
size: 'L',
parts: Parts.new([chain,
road_tire,
tape]))
puts road_bike.size
#puts road_bike.parts.size
puts road_bike.spares.size
很明显,这一行->puts road_bike.spares.size给出了错误NoMethodError,但是,我不确定如何解决此示例中的此问题。spares方法返回一个Part对象数组,但是我的问题似乎在于spares方法.select在调用对象中是私有的
任何修改此代码的建议都将非常有用。谢谢 这里发生的是Partsparts为零。您将在这一行中看到错误:
# parts is nil
parts.select{|part| part.needs_spare}
在零件的初始值设定项中,未正确指定其零件属性:
def initialize(args={})
@parts = parts
end
因此,在初始化时,它会将parts的值赋给@parts。但由于parts在那里不是局部变量,因此它调用Partsparts方法,该方法返回nil
如果将初始值设定项更改为以下内容:
def initialize(parts)
@parts = parts
end
您将能够运行代码。但是Parts的子类似乎希望在初始值设定项中使用散列,而不是像它们的超类那样使用数组。异常清楚地表明,您正在调用nil上的spares方法。看看代码,我也怀疑你是否知道自己在做什么。为什么不是AR?谢谢你的快速回复。我不知道你问AR时指的是什么?你能澄清一下吗?这篇文章是关于普通Ruby而不是Rails的,因此这些不是AR ActiveRecord实例。尽管在Rails中,您也可以拥有非AR子类的类@Michal Szyndel@fivedigit我知道,但如果它看起来像AR和江湖郎中一样,我可能会认为有什么可疑的事情发生了,对吗?你必须承认,它非常像AR…@Michal Szyndel,这是真的。如果我没有弄错的话,这段代码实际上是基于Sandy MetzThank在Ruby中的实际面向对象设计的一个示例,感谢您对子类的响应和后续操作。在我看完这些示例后,下一部分将讨论数组问题以及重构代码的可能选项。