Lately I came across some weird behavior with the defined?
operator used to check if super
keyword can be used in current context. Usually it works fine, but when I tried to combine the defined? super
check with a tiny bit of metaprogramming, it gave me unexpected results.
最近我遇到了一些奇怪的行为与定义?运算符用于检查是否可以在当前上下文中使用super关键字。通常它工作正常,但当我试图结合定义?用一点点的元编程超级检查,它给了我意想不到的结果。
It's easier to show then to describe, so here is a distilled example to illustrate the problem:
然后展示更容易描述,所以这里有一个举例说明问题:
class A;
def self.def_f!;
singleton_class.send(:define_method, :f) { defined? super }
end
end
class AA < A; end
(A
and AA
classes both have .def_f!
class method)
(A和AA类都有.def_f!类方法)
A.def_f!
A.f # => nil
AA.f # => nil
(A.f
has no super and AA.f
dispatches to A.f
, so everything's OK so far, but...)
(A.f没有超级和AA.f派遣到A.f,所以一切都好,到目前为止,但......)
AA.def_f! # define its own .f method in the AA class
AA.f # => "super"
A.f # => "super" # WHY???
Could anyone explain me the last line? A.f
has no super method, then why it returns "super"
instead of nil
? Is it a bug?
谁能解释我最后一行? A.f没有超级方法,那为什么它返回“super”而不是nil?这是一个错误吗?
(I tried it in 1.9.2 and 1.9.3—same results)
(我在1.9.2和1.9.3中尝试过 - 相同的结果)
UPD: I opened a ticket on the Ruby bugtracker: http://bugs.ruby-lang.org/issues/6644
UPD:我在Ruby bugtracker上开了一张票:http://bugs.ruby-lang.org/issues/6644
2 个解决方案
#1
2
Ok, so @Niklas was right, I reported this issue to the Ruby bugtracker and they confirmed and fixed the bug: https://bugs.ruby-lang.org/issues/6644.
好的,所以@Niklas是对的,我向Ruby bugtracker报告了这个问题,他们确认并修复了这个bug:https://bugs.ruby-lang.org/issues/6644。
As far as I've understood, the fix will be included in ruby 2.0.0.
据我所知,修复程序将包含在ruby 2.0.0中。
#2
1
Yeah there are a few quirks with define_method
, this is not a problem with defined?(super)
really, but more with define_method
. Having said that, whenever I encounter an edge case like this with define_method
, I usually just end up eval'ing a string of Ruby code and it always ends up working as expected.
是的,define_method有一些怪癖,这不是定义的问题吗?(超级)真的,但更多的是使用define_method。话虽如此,每当我遇到像这样的边缘情况下使用define_method时,我通常只是最终评估一串Ruby代码并且它总是按预期工作。
module M;
def def_f!
singleton_class.class_eval <<-RUBY
def f
defined?(super)
end
RUBY
end
end
class A; extend M; end
class AA < A; end
A.def_f!
p A.f # => nil
p AA.f # => nil
AA.def_f! # define its own .f method in the AA class
p AA.f # => "super"
p A.f # => nil
As to why it works this way, I'm not experienced enough with Ruby's source to know, maybe somebody who knows more than I do can chime in. But for practical purposes, evaluating a string has always worked for me.
至于为什么它以这种方式工作,我没有足够的经验与Ruby的来源知道,也许比我知道更多的人可以插入。但出于实际目的,评估字符串一直对我有用。
#1
2
Ok, so @Niklas was right, I reported this issue to the Ruby bugtracker and they confirmed and fixed the bug: https://bugs.ruby-lang.org/issues/6644.
好的,所以@Niklas是对的,我向Ruby bugtracker报告了这个问题,他们确认并修复了这个bug:https://bugs.ruby-lang.org/issues/6644。
As far as I've understood, the fix will be included in ruby 2.0.0.
据我所知,修复程序将包含在ruby 2.0.0中。
#2
1
Yeah there are a few quirks with define_method
, this is not a problem with defined?(super)
really, but more with define_method
. Having said that, whenever I encounter an edge case like this with define_method
, I usually just end up eval'ing a string of Ruby code and it always ends up working as expected.
是的,define_method有一些怪癖,这不是定义的问题吗?(超级)真的,但更多的是使用define_method。话虽如此,每当我遇到像这样的边缘情况下使用define_method时,我通常只是最终评估一串Ruby代码并且它总是按预期工作。
module M;
def def_f!
singleton_class.class_eval <<-RUBY
def f
defined?(super)
end
RUBY
end
end
class A; extend M; end
class AA < A; end
A.def_f!
p A.f # => nil
p AA.f # => nil
AA.def_f! # define its own .f method in the AA class
p AA.f # => "super"
p A.f # => nil
As to why it works this way, I'm not experienced enough with Ruby's source to know, maybe somebody who knows more than I do can chime in. But for practical purposes, evaluating a string has always worked for me.
至于为什么它以这种方式工作,我没有足够的经验与Ruby的来源知道,也许比我知道更多的人可以插入。但出于实际目的,评估字符串一直对我有用。