2

メソッド定義のブロックを取り、それをクラスに注入するクラス メソッドを作成したいと考えています。さて、self確かにTomオブジェクトなのでclass << self、それを開きますが、yield機能していないようです. 私の理論的知識はそれほど深くないので、なぜこれが機能しないのかわかりません。私はこれを完全に間違っているかもしれないので、代替案について自由に話し合ってください。

class Tom < Person
  mega_methods do
    def hiya!
      puts 'hiYA!'
    end
  end
end

class Person
  def self.mega_methods
    ...
    class << self
      yield
    end
  end
end

Tom.hiya!

メソッドをTom使用して定義するか、ブロックclass << selfに含めることができることを認識しています。class << self

私はこの代替案も考え出しました:

def self.mega_methods &block
  if block_given?
    extension =  Module.new(&Proc.new)
    self.extend(extension)
  end
end

この質問は、特定の問題を解決するというよりも、Ruby の仕組みを理解するのに役立つものです。

4

1 に答える 1

3

少し奇妙ですが、Ruby を調べているのであれば問題ありません。

class Person
  puts "evaluating Person's body ..."
  def self.mega_methods
      puts 'in Person#self.mega_methods, about to yield ...'
      yield
  end
end

class Tom < Person
  puts "evaluating Tom's body ..."
  print 'Tom.singleton_methods : '; p Tom.singleton_methods
  mega_methods do
    puts 'in Tom, about to define self.hiya!'
    def self.hiya!
      puts 'hiYA!'
    end
  end
  print 'Tom.singleton_methods : '; p Tom.singleton_methods
end

Tom.hiya!

実行:

$ ruby -w t.rb 
evaluating Person's body ...
evaluating Tom's body ...
Tom.singleton_methods : ["mega_methods"]
in Person#self.mega_methods, about to yield ...
in Tom, about to define self.hiya!
Tom.singleton_methods : ["mega_methods", "hiya!"]
hiYA!

メソッド名の感嘆符は、慣例によりString#sub!、レシーバー文字列を変更するメソッドなど、メソッドを破棄するために予約されていることに注意してください。

def `self.function` 名とはどういう意味ですか?も参照してください。

それはすべて自己についてです!

class Person2
  def self.mega_methods
    print 'in Person2 self='; p self
    class << self
      print 'in class << self self='; p self
      yield
    end
  end
end

class Tom2 < Person2
  mega_methods do
    puts "in Tom2, about to define self.hiya! for self=#{self}"
    def self.hiya!
      puts 'hiYA!'
    end
    def hi
      puts 'hi'
    end
  end
end

print 'Tom2.singleton_methods : '; p Tom2.singleton_methods
print 'Tom2.instance_methods  : '; p Tom2.instance_methods(false)
Tom2.hiya!
Tom2.new.hi

実行:

$ ruby -w t2.rb 
in Person2 self=Tom2
in class << self self=#<Class:Tom2>
in Tom2, about to define self.hiya! for self=Tom2
Tom2.singleton_methods : ["mega_methods", "hiya!"]
Tom2.instance_methods  : ["hi"]
hiYA!
hi
于 2013-01-27T13:38:23.333 に答える