@ Readonly
Если ваше использование "class MyObject" является использованием открытого класса, то обратите внимание, что вы переопределяете метод initialize.
В Ruby нет такой вещи, как перегрузка ... только переопределение или переопределение ... другими словами, может быть только 1 экземпляр любого данного метода, поэтому, если вы переопределите его, он будет переопределен ... и метод initialize ничем не отличается (хотя это то, что использует новый метод объектов Class).
Таким образом, никогда не переопределяйте существующий метод без предварительного наложения его на псевдоним ... по крайней мере, если вы хотите получить доступ к исходному определению. И переопределение метода инициализации неизвестного класса может быть довольно рискованным.
Во всяком случае, я думаю, у меня есть для вас гораздо более простое решение, которое использует настоящий метакласс для определения одноэлементных методов:
m = MyObject.new
metaclass = class << m; self; end
metaclass.send :attr_accessor, :first, :second
m.first = "first"
m.second = "second"
puts m.first, m.second
Вы можете использовать как метакласс, так и открытые классы, чтобы стать еще сложнее и сделать что-то вроде:
class MyObject
def metaclass
class << self
self
end
end
def define_attributes(hash)
hash.each_pair { |key, value|
metaclass.send :attr_accessor, key
send "#{key}=".to_sym, value
}
end
end
m = MyObject.new
m.define_attributes({ :first => "first", :second => "second" })
Вышесказанное в основном представляет метакласс с помощью метода «метакласса», затем использует его в define_attributes для динамического определения группы атрибутов с помощью attr_accessor, а затем вызывает установщик атрибутов с соответствующим значением в хэше.
С Ruby вы можете проявить творческий подход и делать одно и то же разными способами; -)
К вашему сведению, если вы не знали, использование метакласса, как я сделал, означает, что вы действуете только с данным экземпляром объекта. Таким образом, вызов define_attributes определит эти атрибуты только для этого конкретного экземпляра.
Пример:
m1 = MyObject.new
m2 = MyObject.new
m1.define_attributes({:a => 123, :b => 321})
m2.define_attributes({:c => "abc", :d => "zxy"})
puts m1.a, m1.b, m2.c, m2.d # this will work
m1.c = 5 # this will fail because c= is not defined on m1!
m2.a = 5 # this will fail because a= is not defined on m2!