Как сделать переменную класса неизменяемой? - PullRequest
0 голосов
/ 04 сентября 2018

Я столкнулся с этой проблемой в онлайн-тесте. У меня есть этот класс:

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 голосов
/ 04 сентября 2018

Это просто делается путем вызова Object#freeze в сочетании с Object#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 для получения противоположного эффекта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...