Это самое близкое к тому, что у тебя было.Я позволил себе сменить его на стандартный стиль кодирования Ruby, но учтите, что единственное реальное изменение - это первая строка add_hello_method_to_class_of
:
class SomeClass; end
class AnotherClass; end
alpha = SomeClass.new
beta = AnotherClass.new
def add_hello_method_to_class_of(obj)
obj.class.send(:define_method, :hello) do
'Hello'
end
end
add_hello_method_to_class_of(alpha)
add_hello_method_to_class_of(beta)
gamma = AnotherClass.new
alpha.hello
beta.hello
gamma.hello
Первоначально у вас было
def obj.class.hello
Это сработает, но не так, как вы думаете.Это добавит одноэлементный метод к самому объекту класса , но, похоже, вы предполагаете, что он добавит экземплярный метод .Если вы хотите добавить метод экземпляра , вам нужно использовать Module#define_method
следующим образом:
obj.class.define_method(:hello)
За исключением того, что Module#define_method
равно private
, поэтому вам нужно использовать отражениечтобы обойти это ограничение доступа:
obj.class.send(:define_method, :hello)
Обратите внимание, что я также изменил название метода с add_hello_method_to
на add_hello_method_to_class_of
, поскольку, не добавляет *Метод 1031 * к аргументу, он добавляет его к классу аргумента .
Однако, если вы делаете патч обезьяны, как это, обычно считается хорошей практикой вместо этого использовать миксины, с тех пормиксин обнаруживается в цепочке наследования объекта, что дает любому отладчику этого кода как минимум реальный шанс выяснить, откуда, черт возьми, этот загадочный метод hello
:
# file: hello_extension.rb
module HelloExtension
def hello
'Hello'
end
end
def add_hello_method_to_class_of(obj)
obj.class.send(:include, HelloExtension)
end
# some other file
require 'hello_extension'
class SomeClass; end
class AnotherClass; end
alpha = SomeClass.new
beta = AnotherClass.new
add_hello_method_to_class_of(alpha)
add_hello_method_to_class_of(beta)
gamma = AnotherClass.new
alpha.hello
beta.hello
gamma.hello
Теперь выможет легко отладить этот код:
gamma.class.ancestors
# => [AnotherClass, HelloExtension, Object, Kernel, BasicObject]
Если кто-то задается вопросом, откуда взялся метод hello
, то не нужно много времени, чтобы выяснить, что миксину под названием HelloExtension
, вероятно, есть чем занятьсяс этим.И, следуя стандартным правилам именования Ruby, они даже знают, что искать в файле с именем hello_extension.rb
Вы даже можете сделать это:
gamma.method(:hello).source_location
# => ['hello_extension.rb', 3]