为什么行,restaurant.menu<lt"比萨饼",修改我们餐厅实例的@menu属性?我对它的理解是餐馆。菜单被称为"甜甜圈","蛋糕"。此时,方法调用完成。那么为什么<lt;pizza影响@menu属性?
class Restaurant
def initialize(name)
@name = name
end
def menu
@menu = @menu || ["donuts", "cake"]
end
end
restaurant = Restaurant.new("Mcdonalds")
p restaurant.menu #["donuts", "cake"]
restaurant.menu << "pizza" #???
p restaurant.menu #["donuts", "cake", "pizza"]>
虽然@red_menace已经回答了根本原因是什么,但我将详细说明这意味着什么。
首先,您需要了解Ruby对象的可变性。在这里你可以找到一些好文章。
基本上,在您的示例中,类的menu
实例方法返回对类实例的实例变量@menu
的引用,该变量是可变数组(您可以通过引用进行修改(。
如果你真的想让它不可变,你可以冻结变量,也可以按照@Jad的建议克隆它。
在这里,你可以找到关于类似问题的精彩讨论。
在这里,您可以看到一个程序跟踪,在您修改menu
方法的返回结果时,您修改了实例变量@menu
。
require 'pp'
class Restaurant
def initialize(name)
@name = name
end
def menu
@menu = @menu || ["donuts", "cake"]
puts "@menu object_id = #{@menu.object_id}"
@menu
end
end
restaurant = Restaurant.new("Mcdonalds")
p restaurant.menu #["donuts", "cake"]
pp "object instance variables are #{restaurant.instance_variables}"
restaurant.menu << "pizza" #???
p restaurant.menu #["donuts", "cake", "pizza"]>
p "restaurand.menu.object_id = #{restaurant.menu.object_id}"
这是程序的输出:
$ruby main.rb
@menu object_id = 47245049576960
["donuts", "cake"]
"object instance variables are [:@name, :@menu]"
@menu object_id = 47245049576960
@menu object_id = 47245049576960
["donuts", "cake", "pizza"]
@menu object_id = 47245049576960
"restaurand.menu.object_id = 47245049576960"
正如@red_menace所建议的,可能值得尝试以下内容:
class Restaurant
def initialize(name)
@name = name
@menu = ["donuts", "cake"]
end
def menu
@menu.dup
end
end