Ruby:数组的类attr_reader能够对数组值进行写访问吗?

时间:2013-03-01 02:59:49

标签: ruby arrays setter getter

这是 attr_reader 应该与数组一起使用的方式吗?

class User
  def initialize
    @interests = []
  end
  attr_reader :interests
end

u = User.new

=> #User:0x1d2cb60

u.interests << "music"

=> ["music"]

u.interests[1] = "travelling"

=> ["travelling"]

u.interests = nil

NoMethodError: undefined method `interests=' for u:User

我只是检查我自己的解释是否正确,如果没有,请纠正我:

attr_reader是不是阻止我分配“@interests”值,因为你没有直接修改实例变量本身(它仍然保存对数组对象的引用),但你只是在操作数组对象引用的值?

如果这是正确的,是否有一种快速而好的方法可以避免attr_reader让我对数组值进行写访问,但让我阅读它们?

由于

2 个答案:

答案 0 :(得分:2)

关于“不直接修改实例变量”,您所描述的内容是正确的。 @interests没有变化,但是因为它是一个可变对象,所以来电者可以潜入你身后。

如果您想禁止编辑:interests字段,只需freeze即可。时间很棘手,因为你想在将对象交还给用户之前阻止写入,所以你可能需要在对象创建时这样做:

def initialize(whatever)
   @foo = bar
   @interests = %w(a b c).freeze
end

如果您的对象想要更改@interests,请小心。您需要完全重建阵列,因为您无法解冻对象。

答案 1 :(得分:1)

编写您自己的getter,并使用dup提供原始数组的副本:

def interests
  @interests.dup
end

完整代码:

class User
  def initialize
    @interests = []
  end

  def interests
    @interests.dup #
  end
end

# Without dup:
u.interests # => []
u.interests << "music"
u.interests # => ["music"]

# With dup:
u.interests # => []
u.interests << "music"
u.interests # => []

(当然,对于多维数组和类似的分层数据结构,您需要稍微更先进的解决方案)