Вместо переменной экземпляра на ключ, который требует некоторого излишне громоздкого кода, почему бы не просто один хеш, как показано ниже. Кроме того, define_method
и define_singleton_method
может быть вашим другом, чтобы избежать плохих ошибок eval
s.
class MyStorageClass
def initialize
@data = {}
end
def add_entry(key, value)
(@data[key] ||= []) << value
define_singleton_method(key){ @data[key] }
end
def get_entry(key)
@data.key?(key) or raise NoMethodError
@data[key]
end
end
Вы можете проверить, что вы не перекрывая предопределенный метод первого ([email protected]?(key) && self.respond_to?(key)
в верхней части метода будет делать add_entry
), но это для другого разговора. Может быть плохо, если кто-то попытался добавить ключ, который называется inspect
, class
, или, о, get_entry
, например!
Вы могли бы также INIT @data с Hash.new {[]}, так что вам не нужно, || = часть в add_entry методе – karina
Danger ! Это должно быть «Hash.new {| h, k | h [k] = []} ', иначе все новые ключи получат значения, связанные с другими. Объект [], который вы передали, представляет собой единый объект в памяти, на который будут ссылаться все ключи, а используемый нами '<<' -модуль изменяет этот объект на месте. Попробуйте! 'h = Hash.new ([]); h [: x] << 1; h [: y] 'дает вам' [1] '. Обычно я предпочитаю инициализатор блока для Hash, если он более выгоден, чем сохранение '|| =' –
. Я использовал фигурные скобки. – karina