🔥

[Bug #20620] 自身を extend したときの .singleton_method に関するバグ報告

2024/07/11に公開

[Bug #20620] singleton_method undefined for module using "extend self"

  • 以下のように extend self したときに self のメソッドが .singleton_method で取得することができないバグ報告
  • 通常は以下のようにクラスメソッドが定義されている場合は .singleton_method でクラスメソッドのオブジェクトを取得することができます
class Klass
  def self.foo
  end
end

p Klass.singleton_methods
# => [:foo]

p Klass.singleton_method(:foo)
# => #<Method: Klass.foo() singleton_method.rb:2>
  • しかし、以下のように自身を extend した場合にうまく取得することができないとのこと
module ExtendSelf
  extend self

  def foo
  end
end

p ExtendSelf.singleton_methods
# => [:foo]

# error: `singleton_method': undefined singleton method `foo' for `ExtendSelf' (NameError)
p ExtendSelf.singleton_method(:foo)
  • これなんですが .singleton_method は『特異クラスに定義されているメソッドを返す』ことになります
  • なので前者の Klass.singleton_method(:foo).foo が特異クラスにメソッドが定義されているので問題ありません
  • しかし、後者の ExtendSelf.singleton_method(:foo).foo が特異クラスではなくて『継承リストのモジュール内で定義されている』ので厳密にいうと特異メソッドとしては扱われない感じですかね
  • また .singleton_methods に関しては引数がない場合は『継承した特異メソッドも含む』になるので ExtendSelf.singleton_methods:foo が含まれます
  • ただし .singleton_methods(false) にすることで『継承した特異メソッドを含まない』になり :foo が含まれなくなります
module ExtendSelf
  extend self

  def foo
  end
end

# こっちは継承した特異メソッドを含む
p ExtendSelf.singleton_methods
# => [:foo]

# こっちは継承した特異メソッドを含まない
p ExtendSelf.singleton_methods(false)
# => []
GitHubで編集を提案

Discussion