#ruby
#ruby
Вопрос:
Я хочу изменить метод singleton_class определенного класса, чтобы он выполнял то же самое, что и раньше, но также делал что-то еще, например, помимо того, что он делал, для выполнения:
- помещает «привет»
Хорошо, итак, я знаю, как переопределить обычный метод класса, чтобы он фактически делал то же самое, что и раньше, но также делал что-то еще, это было бы так:
class Class
def addHelloToMethod(methodName)
unboundMethod = instance_method(methodName)
define_method(methodName) do |*args, amp;block|
result =unboundMethod.bind(self).(*args, amp;block)
puts "hello"
result
end
end
end
Что мне нужно, так это добавить это «привет» к методу
singleton_class, поэтому я попробовал это:
class Class
def addHelloToSingletonClassMethod(methodName)
unboundMethod = singleton_class.instance_method(methodName)
singleton_class.define_method(methodName) do |*args, amp;block|
result =unboundMethod.bind(self).(*args, amp;block)
puts "hello"
result
end
end
end
Что я здесь делаю не так?
Ответ №1:
Один из способов сделать это — добавить анонимный модуль, который переопределяет требуемый метод, печатает hello и вызывает super
для вызова фактической реализации.
Я не уверен, почему вы добавляете этот метод Class
. Ваша цель — вызвать addHelloToSingletonClassMethod
экземпляр такого класса, как этот?
irb> s = "foo"
irb> s.addHelloToSingletonClassMethod(:upcase)
irb> s.upcase
hello
=> "FOO"
Если это так, определите следующее на Object
:
class Object
def addHelloToSingletonClassMethod(methodName)
mod = Module.new
mod.define_method(methodName) do |*args, amp;blk|
puts "hello"
super(*args, amp;blk)
end
singleton_class.prepend(mod)
end
end
Или в более типичном соглашении об именах Ruby:
class Object
def add_hello_to_method(name)
mod = Module.new
mod.define_method(name) do |*args, amp;blk|
puts "hello"
super(*args, amp;blk)
end
singleton_class.prepend(mod)
end
end
Если ваша цель, с другой стороны, состоит в том, чтобы иметь возможность вызывать его в классе следующим образом
irb> String.addHelloToSingletonClassMethod(:upcase)
irb> "foo".upcase
hello
=> "FOO"
затем вы хотите определить его на Class
:
class Class
def add_hello_to_method(name)
mod = Module.new
mod.define_method(name) do |*args, amp;blk|
puts "hello"
super(*args, amp;blk)
end
prepend(mod)
end
end
Ответ №2:
Измените изменение addHelloToSingletonClassMethod
на self.addHelloToSingletonClassMethod
. Это должен быть метод класса.
Комментарии:
1. Чтобы определить метод в классе singleton_class, я хочу переопределить метод в экземпляре класса singleton_class.