Ruby类和属性字段

时间:2014-11-02 12:42:48

标签: ruby-on-rails ruby

我正在尝试制作一个Zar类,它可以模拟我5个骰子的滚动(对于ruby koans教程)。我目前无法访问我创建的数组。我正在改变价值观但不知何故它现在正在显示。 此外,我有3个与此问题相关的问题。

  1. 当使用attr_accessor :name声明属性字段时,如何访问为创建数组而创建的新:name,我可以在初始化程序中说:name = [0,0,0,0,0]
  2. 如何访问使用@name
  3. 定义的属性
  4. 以及:@name
  5. 之间的区别是什么?

    我将发布以下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
    

3 个答案:

答案 0 :(得分:2)

好的,想想

attr_accessor :name

作为声明ruby类setter&的快捷方式getter用于名为@name的实例变量,快速简便的编写方式:

def class Zar
  def name
    @name
  end

  def name=(value)
    @name = value
  end
end

回答你的问题:

  1. 您可以通过initilize方法
  2. 初始化对象实例变量
  3. 您可以使用. z.name来访问对象的实例变量,例如
  4. :name是我们如何告诉ruby我们需要setter / getter /或两者兼容一个名为@name的实例变量
  5. 那么,你的代码有什么问题,你似乎已经在第二次尝试中应用了所有这些?

    嗯,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)

  
      
  1. 使用以下内容声明属性字段时:attr_accessor :name   你如何访问新的:为了制作数组而创建的名称我可以说:初始化器中的name = [0,0,0,0,0]?
  2.   

你没有。您可以在内部访问@name,在外部访问name:name符号,它不是变量的名称。

  
      
  1. 如何访问使用@name
  2. 定义的属性   

@name内部。如果没有定义访问者,则无法在课外访问它

  
      
  1. name和@name之间的区别是什么?
  2.   

一切。一个是实例变量,另一个是符号。他们完全不同。


确定。你在这里很困惑。

在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 :nameattr_accessor 'name'时,只需调用带参数的方法,参数就是要定义的方法的名称。它将为您创建上述def namedef 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中一个非常重要的模块,我建议你多次阅读这些文档。

http://ruby-doc.org/core-2.1.4/Enumerable.html