Ответ 1
Там нет ничего волшебного или о модели рельсов, это просто обычный класс с кучей ранее существовавших методов,
Итак, вопрос: "Могу ли я определить метод в классе"?
Часть 1: Да, вы можете.
Важным отличием является то, что вы можете определить метод в классе, а не в методе экземпляра
Например:
class Cow
define_method "speak" do
"MOOOO"
end
end
Cow.new.speak
=> "MOOOO"
Это должно работать нормально. Обратите внимание, что вы определяете его в классе Cow, поэтому любые другие коровы, которые у вас уже есть, автоматически получат этот метод.
Часть 2: Что вы делаете, если хотите определить метод из метода экземпляра?
Вы не можете определять методы из метода экземпляра, поэтому вам нужно схватить класс и использовать его для определения метода. Вот так:
class Cow
def add_speak
self.class.send(:define_method, :speak) do
"MOOOO added"
end
end
end
Cow.new.speak
NoMethodError: undefined method 'speak' for #<Cow:0xb7c48530>
Cow.new.add_speak
Cow.new.speak
=> "MOOOO added"
Проблема решена. Астуальные читатели заметят, что в этом примере я использую send(:define_method)
- это необходимо, потому что define_method
является закрытым, а частные методы доступны только для того, в котором они находятся. В этом случае define_method
находится в class, мы находимся в этом экземпляре, поэтому мы не можем напрямую обращаться к нему.
Как указано выше, мы добавляем метод непосредственно к классу, поэтому все остальные коровы, которые уже существуют, автоматически также получат добавленный метод выражения.
Часть 3: Что вы делаете, если хотите определить метод только для одного объекта, а не для всех объектов этого класса?
Пример:
class Cow
def add_speak_just_me
class << self
define_method "speak" do
"MOOOO added for just me"
end
end
end
end
Cow.new.speak
NoMethodError: undefined method 'speak' for #<Cow:0xb7c72b78>
c = Cow.new
c.add_speak_just_me
c.speak
=> "MOOOO added for just me" # it works, hooray
Cow.new.speak # this new cow doesn't have the method, it hasn't been automatically added
NoMethodError: undefined method `speak' for #<Cow:0xb7c65b1c>
Как это работает? Вниз по раввилону, ты идешь!
Прочтите это: http://dannytatom.me/metaid/ и удачи. Это помогает, когда вы понимаете, что "добавление метода" в экземпляр фактически не добавляет его в экземпляр: -)