#ruby #metaprogramming
#ruby #метапрограммирование
Вопрос:
В (автоматических) образовательных целях я пытаюсь имитировать super
поведение, чтобы узнать, как это работает.
Я мог бы имитировать super
, например, методы, но я не мог этого сделать для методов класса.
Вот мой код:
class A
def aa
@msg ||= 'Original...: '
puts "#{@msg}#{self}.aa: #{self.class} < #{self.class.superclass}"
end
def self.ab
@msg ||= 'Original...: '
puts "#{@msg}#{self}.ab: #{self} < #{self.superclass}"
end
end
class B < A
def aa
@msg = "Real super.: "
super
end
def self.ab
@msg = "Real super.: "
super
end
def mimic_aa
@msg = "Mimic super: "
self.class.superclass.instance_method(:aa).bind(self).call
end
def self.mimic_ab
@msg = "Mimic super: "
#superclass.method(:ab).unbind.bind(self).call
#=> Error: singleton method only works in original object
#superclass.ab
#=> self is A; I want self to be B
proc = superclass.method(:ab).to_proc
#self.instance_eval(amp;proc)
#=> ArgumentError: instance_eval seems to call aa(some_unwanted_param)
# Note: Ruby 1.8.7
#eval('proc.call', binding)
#=> self is A; I want self to be B
end
end
a = A.new
b = B.new
a.aa #=> Original...: #<A:0xb77c66ec>.aa: A < Object
b.aa #=> Real super.: #<B:0xb77c6624>.aa: B < A
b.mimic_aa #=> Mimic super: #<B:0xb77c6624>.aa: B < A
puts ''
A.ab #=> Original...: A.ab: A < Object
B.ab #=> Real super.: B.ab: B < A
B.mimic_ab #=> (expected the same as above)
Есть идеи?
Комментарии:
1. Ваш вопрос слишком сложный и непонятный. Я думаю, именно поэтому на ваш вопрос пока нет ответа. Что вы пытаетесь сделать с
B#mimic_aa
иB.mimic_ab
? Почему будетB#aa
иB.ab
недостаточно? Кроме того, названия методов сбивают с толку. Возможно, вы захотите улучшить вопрос.2. @sawa, я хочу узнать, как выполнить метод класса в A в контексте того, что B является
self
. Это может быть полезно, когда имена методов в A и B разные, и поэтому я не смог использоватьsuper
. В любом случае, спасибо, я подумаю над улучшением вопроса. 🙂
Ответ №1:
Что ж, проблема, вероятно, в используемой вами версии Ruby. Я использую 1.9.2, и программа выполняется, как ожидалось. Я думаю (из комментария в вашем коде), что проблема в том, что вы используете Ruby версии v1.8.7. Также не помешало бы попробовать запустить ваш код еще раз.
Комментарии:
1. Круто! Используете ли вы
self.instance_eval(amp;proc)
?2. Это было определение, которое работает:
def self.mimic_ab; @msg = "Mimic super: "; superclass.method(:ab).unbind.bind(self).call; end