关于attr_accessor,实例变量,局部变量的ruby

时间:2018-01-11 15:28:44

标签: ruby-on-rails ruby

我对此很困惑.. 像这样

class Box 
   attr_accessor :item ,:item2  

   def initialize(item2)
      @item = []
      @item2 = item2
   end

   def add(product)
      item << product
   end

   def empty?
      item.empty?
   end

   def increment(n=1)
      item2 +=1
   end

end

cart =Box.new(123)
cart.add(1)
puts cart.empty? #false
puts cart.item   #1

在&#39;添加&#39;并且空了?&#39;方法 我使用本地变量&#39; item&#39;对? 为什么我可以从@items获得价值?

我试试这个

cart.item2 = 345
puts cart.item2  #345
puts cart.increment #'increment': undefined method `+' for nil:NilClass (NoMethodError)

现在我无法获得价值?

请修好我的脑子

1 个答案:

答案 0 :(得分:4)

首先,阅读this answer,这是StackOverflow历史记录中最受欢迎的Ruby帖子。它有助于您了解attr_accessor及其堂兄attr_readerattr_writer

除此之外,您的代码还有很多问题。

首先,不应将具有单数变量名称的数组命名为item。使用复数items来明确其目的。

其次,名称item2并不好。对于您的属性,请使用像counter这样的描述性内容,对于作为参数传递的变量来初始化它,让我们使用像initial_count这样的描述性内容。

第三,你的increment方法接受一个可选参数但忽略它。如果有人调用box.increment(2)并且属性仅增加1,那会不会令人惊讶?此方法的目的是使用counter += n而不是counter += 1

第四,要在班级中设置counter,我们需要使用self。因此,我们必须counter += n而不是self.counter += n

最后,考虑是否希望属性从外部源可读写,或者是否要保留对象本身的写权限。因为您有方法可以向items添加内容并增加counter,所以您可能希望隐藏写权限。我会公开使用attr_reader,私下使用attr_writer

结合这些建议,这是结果代码:

class Box
  attr_reader :counter, :items

  def initialize(initial_count)
    @counter = initial_count
    @items = []
  end

  def add(product)
    items << product
  end

  def empty?
    items.empty?
  end

  def increment(n = 1)
    self.counter += n
  end

  private

  attr_writer :counter, :items
end

现在你可以做到这一点,所有这些都有意义,或多或少:

>> cart = Box.new(123)
>> cart.increment(2)
>> cart.counter
#> 125
>> cart.add('A product')
>> cart.add('Another product')
>> cart.items
#> ["A product", "Another product"]

但如果您尝试直接设置counteritems,则会收到错误消息:

>> cart.counter = 1
#> NoMethodError: private method `counter=' called for #<Box:0x007fc13e17dc50>