从attr_reader返回变量的别名是否安全?

时间:2014-10-12 12:13:49

标签: ruby oop

首先,让我介绍一个代码示例:

class BankAccount
  attr_reader :allowed_users

  def initialize(allowed_users)
    @allowed_users = allowed_users
  end

end

因此我们都知道我们可以致电b = BankAccount.new %w( john alice )来创建BankAccount个实例。

我不想attr_writer(让我们说要更改allowed_user数组我希望有一些PIN码逻辑)

所以现在我无法致电b.allowed_users= %w( john annie ),但我怎么可以致电b.allowed_users[1] = 'anie'来修改@allowed_users数组。

如何处理?这是attr_reader应该如何工作还是某种错误?

我知道有.freeze方法的解决方案,但

怎么办?
def allowed_users
  self.allowed_users.dup
end
哪个更有效率?

1 个答案:

答案 0 :(得分:0)

attr_reader只定义了实例变量的getter方法。因此,在您的情况下,b.allowed_users[1] = 'anie'不会重新定义实例变量@allowed_users,它只会更改在实例变量中保存地址的对象。

你正确地指出,要解决这个问题,你需要使用不可变对象或编写自己的getter方法,它不能直接返回对象。

我认为freeze更适合,因为当您尝试修改对象时,它会明确地抛出错误:

2.1.1 :001 > arry = [1,2,3].freeze
 => [1, 2, 3] 
2.1.1 :002 > arry << 4
RuntimeError: can't modify frozen Array

因此,如果您不熟悉课程实施,那么您将无法犯错:

bank_account = BankAccount.new(User.limit(10))
bank_account.allowed_users << User.first
bank_account.allowed_users # at this step you expect to have allowed_users == User.take(10) + [User.last]