这是一个Ruby Monk练习,我无法绕过一个特定的概念。
例如,"soup bowl" = "soup bowl" + 1
无效,那么为什么@dishes_needed[a] = (@dishes_needed[a] || 0) + 1
可以在下面的代码中使用?是因为它们是变量而不是对象吗?如果是这样,为什么我最初设置a = (a||0)+1
时代码a = "Soup"
无效:
class Dish
end
class Soup < Dish
end
class IceCream < Dish
end
class ChineseGreenBeans < Dish
end
class DeliveryTray
DISH_BOWL_MAPPING = {
Soup => "soup bowl",
IceCream => "ice cream bowl",
ChineseGreenBeans => "serving plate"
}
def initialize
@dishes_needed = {}
end
def add(dish)
a = DISH_BOWL_MAPPING[dish.class]
@dishes_needed[a] = (@dishes_needed[a] || 0) + 1
end
def dishes_needed
return "None." if @dishes_needed.empty?
@dishes_needed.map { |dish, count| "#{count} #{dish}"}.join(", ")
end
end
d = DeliveryTray.new
d.add Soup.new; d.add Soup.new
d.add IceCream.new
puts d.dishes_needed # should be "2 soup bowl, 1 ice cream bowl"
答案 0 :(得分:3)
让我们简化@dishes_needed
部分,以便您了解核心概念。 @dishes_needed
是一个哈希值,@dishes_needed[a] = (@dishes_needed[a] || 0) + 1
为哈希值添加一个键值对。
这是查看代码的更简单方法。这是DISH_BOWL_MAPPING哈希:
DISH_BOWL_MAPPING = {
Soup => "soup bowl",
IceCream => "ice cream bowl",
ChineseGreenBeans => "serving plate"
}
从DISH_BOWL_MAPPING
哈希中获取某个元素:
>> DISH_BOWL_MAPPING[Soup]
=> "soup bowl"
@dishes_needed
是一个空哈希:
>> @dishes_needed = {}
=> {}
如果a = Soup
,那么这就是所讨论的代码行的运作方式:
>> a = Soup
=> Soup
>> @dishes_needed[a] = (@dishes_needed[a] || 0) + 1
=> 1
>> @dishes_needed
=> {Soup=>1}
让我们分解混淆等式的右边:
>> (@dishes_needed[a] || 0) + 1
>> (@dishes_needed[Soup] || 0) + 1
# @dishes_needed[Soup] is nil because Soup hasn't been added to the hash yet
>> (nil || 0) + 1
# nil || 0 evaluates to 0 because nil and false are falsey in Ruby
>> (0) + 1
>> 1
后来调用@dishes_needed[Soup]
评估为1,现在哈希已更新:
>> @dishes_needed[Soup]
=> 1
这表示密钥(Soup)等于值加1(在这种情况下,该值尚未建立,因此导致1)。
如果a = "Soup"
,则a = (a||0)+1
评估为a = "Soup" + 1
,并且您无法在Ruby中添加整数和字符串。如果将1转换为字符串,则表达式将正确计算。
a = (a||0)+1.to_s
答案 1 :(得分:2)
我们不能将事物划分为ruby中的变量和对象。这里的一切都是一个对象。
关于你的代码唯一需要理解的是+方法(是的,它是一个方法)不会像你在两种情况下尝试的那样使用字符串对象。它适用于那种情况,因为如果对象是NILL,你用Fixnum对象初始化它0和+方法与Fixnum一起正常工作。
希望我能回答你。如果需要更多说明,请询问。答案 2 :(得分:1)
在此代码中:
a = DISH_BOWL_MAPPING[dish.class]
@dishes_needed[a] = (@dishes_needed[a] || 0) + 1
a
要么是来自DISH_BOWL_MAPPING
哈希值中的一个值的字符串,要么是nil
,如果密钥不在那里。如果是nil
,则@dishes_needed[a]
也将为零,这会使(@dishes_needed[a] || 0)
评估为0
,然后您将1
添加到Hash#[]
。这里的关键概念是nil
如果找不到密钥则返回@dishes_needed[a]
(除非你将默认设置为其他东西,你没有在这里)。显然,这里的净效果是如果它已经存在则递增1
,或者如果它不存在则将其设置为a = "Soup"
a = (a||0)+1
。
与之对比:
a
此处,"Soup"
始终以(a||0)
开头,因此"Soup"
始终为1
,您无法将{{1}}添加到。{/ p>