我正在尝试制作一个Zar类,它可以模拟我5个骰子的滚动(对于ruby koans教程)。我目前无法访问我创建的数组。我正在改变价值观但不知何故它现在正在显示。 此外,我有3个与此问题相关的问题。
attr_accessor :name
声明属性字段时,如何访问为创建数组而创建的新:name
,我可以在初始化程序中说:name = [0,0,0,0,0]
? @name
@name
?我将发布以下2次尝试进行Zar
班级工作:
第一:
class Zar
def initialize
@score = 0
@rolled = [0,0,0,0,0]
end
def roll
@rolled.each do |item|
item = 1 + rand(6)
end
end
def show_rolled
@rolled.each do |item|
print item
end
end
end
#test
z = Zar.new()
z.roll
z.show_rolled
第二
class Zar
attr_accessor :rolled
attr_accessor :score
def initialize
@score = 0
@rolled = [0,0,0,0,0]
end
def roll
@rolled.each { |item|
item = 1 + rand(6)
}
end
end
#test
z = Zar.new()
z.roll
print z.rolled
答案 0 :(得分:2)
好的,想想
attr_accessor :name
作为声明ruby类setter&的快捷方式getter用于名为@name的实例变量,快速简便的编写方式:
def class Zar
def name
@name
end
def name=(value)
@name = value
end
end
回答你的问题:
initilize
方法.
z.name
来访问对象的实例变量,例如:name
是我们如何告诉ruby我们需要setter / getter /或两者兼容一个名为@name的实例变量那么,你的代码有什么问题,你似乎已经在第二次尝试中应用了所有这些?
嗯,roll
方法中的小问题,你通过已启动的数组循环但从未告诉方法更改对象@rolled数组。
这是一次尝试:
class Zar
attr_accessor :rolled, :score
def initialize
@score = 0
@rolled = [0,0,0,0,0]
end
def roll
@rolled.map! { |item| item = 1 + rand(6) }
# map with bang (!) is the same as: @rolled = @rolled.map { |item| item = 1 + rand(6) }
end
end
#test
z = Zar.new()
z.roll
print z.rolled
答案 1 :(得分:2)
- 使用以下内容声明属性字段时:
醇>attr_accessor :name
你如何访问新的:为了制作数组而创建的名称我可以说:初始化器中的name = [0,0,0,0,0]?
你没有。您可以在内部访问@name
,在外部访问name
。 :name
是符号,它不是变量的名称。
- 如何访问使用@name
定义的属性 醇>
@name
内部。如果没有定义访问者,则无法在课外访问它
- name和@name之间的区别是什么?
醇>
一切。一个是实例变量,另一个是符号。他们完全不同。
确定。你在这里很困惑。
在Ruby中,@name
是当前类的实例变量。当你在该类的上下文中时(在其中一个方法中),你可以读取和写入它,但你不能从该类之外读取或写入它。
为此,您需要定义访问者方法。通常,访问器方法与@variable
具有相同的名称,但它们没有@
前缀,因为它们是方法而不是实例变量。
所以,如果我的课上有变量@name
,我会通过“getter”方法给外部代码访问读取:
def name
@name
end
现在,人们可以使用some_instance_of_my_class.name
来访问@name
。在内部,您现在可以访问name
方法来阅读@name
,这通常是一个好主意。
如果我想让人们具有写访问权限,我会定义一个 setter ,它在Ruby中有一个特殊的语法:
def name=(value)
@name = value
end
现在,人们可以使用some_instance_of_My_class.name = "new name"
将写入@name
。在内部,您可以使用name=
写入名称,但必须在其前面添加self.name=
,否则Ruby会假定您正在定义一个名为name
的新局部变量。
所以,attr_accessor
。这只是一种方法,就像任何其他方法一样,除了它为您做一些元编程。使用attr_accessor :name
或attr_accessor 'name'
时,只需调用带参数的方法,参数就是要定义的方法的名称。它将为您创建上述def name
和def name=
方法,使用相同的方法体,包围@name
变量。
如果你写了attr_accessor :bob
,那就会给你:
def bob
@bob
end
def bob=(value)
@bob = value
end
关于你的具体问题:
@rolled.each do |item|
item = 1 + rand(6)
end
这不起作用,因为item
按值传递给block
。循环中的item
变量是自己的变量,通过赋值修改它不会影响@rolled
中存储的值。要更改这些值,您需要直接分配到@rolled
。
您可以使用map
轻松完成此操作,使用新数组覆盖整个数组:
@rolled = (1..6).map do |roll|
rand(1..6)
end
您可以对each_with_index
的单个项执行此操作,但是当整个数组都填充0
时,没有任何值可以执行此操作:
@rolled.each_with_index do |item,index|
@rolled[index] = rand(1..6)
end
答案 2 :(得分:1)
关于attr_accessor,请查看此答案 :What is attr_accessor in Ruby?
tldr,attr_accessor使用传递的符号作为方法名为您创建一个get和set方法。 它还使用相应的名称创建支持实例变量。
class Zar
attr_accessor :score
attr_accessor :rolled
def intialize
self.score = 0 #you could use @score too
self.rolled = [0,0,0,0,0] #you could use @rolled too
end
end
关于roll方法的实现: 当您使用每个项进行迭代时,将为数组中的每个项调用您的块,并且该项将作为参数传递。 在您的情况下,变量名为' item'包含对数组中项目的引用。
然后你将一个新值(1 + rand(6))分配给'项目'变量,它不会改变数组中的值。
有很多方法可以在ruby中完成你想要的东西,例如:
def roll
self.rolled = 6.times.map do
rand(6)
end
end
Enumerable是Ruby中一个非常重要的模块,我建议你多次阅读这些文档。