如何使类变量不可修改?

时间:2018-09-04 04:53:06

标签: ruby

我在在线测试中遇到了这个问题。我有这个课:

class DocumentStore
  def initialize(capacity)
    @capacity = capacity;
    @documents = []
  end

  def get_documents
    return @documents
  end

  def add_document(document)
    raise 'Document store is full' if @documents.length >= @capacity
    @documents.push(document)
  end

  def inspect
    return "Document store: #{@documents.length}/#{@capacity}"
  end
end

我想通过get_documents返回存储数据,并防止用户通过返回的对象(例如,

)更改/影响其值。
ds = DocumentStore.new(3)
ds.add_document("Doc1")

docs = ds.get_documents
docs.push("Doc2")

puts ds.inspect # this should just print ["Doc1"]

1 个答案:

答案 0 :(得分:4)

只需将Object#freezeObject#dup一起调用即可完成。 freeze 不返回冻结的副本,而是冻结self并返回self。这意味着没有 dup 调用,您也无法在类内部修改数组。

def get_documents
  return @documents.dup.freeze
end

您还可以选择仅使用 dup ,返回浅表副本。允许调用者修改数组而不影响@documents

def get_documents
  return @documents.dup
end

注意:请记住,没有其他方法可以检索数组。 Ruby总是返回方法所做出的最后一条语句。这意味着您的方法DocumentStore#add_document将返回@documents.push(document)的结果。

Array#push

  

Append —将给定对象推到该数组的末尾。此表达式返回数组本身,因此可以将多个追加链接在一起。另请参见#pop,以了解相反的效果。