【问题标题】:Is returning alias of variable from attr_reader secure?从 attr_reader 返回变量的别名是否安全?
【发布时间】:2014-10-12 12:13:48
【问题描述】:

首先介绍一个代码示例:

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

哪一个更有效?

【问题讨论】:

  • 在“我不想关闭attr_writer(”处打开的括号在哪里?使用正确的大小写。很难阅读。

标签: ruby oop


【解决方案1】:

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]

【讨论】:

    猜你喜欢
    • 2020-06-22
    • 2016-02-09
    • 1970-01-01
    • 2020-03-09
    • 2014-01-05
    • 1970-01-01
    • 2010-10-02
    • 2014-12-20
    • 2020-09-10
    相关资源
    最近更新 更多