定义?(超级)检查的奇怪行为

时间:2022-06-04 17:27:05

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的来源知道,也许比我知道更多的人可以插入。但出于实际目的,评估字符串一直对我有用。