5

以下は、 Why's Poignant Guide to Ruby Chapter 6からの Ruby コード スニペットで、Rubyでのメタプログラミングのデモンストレーションを試みています。

# Get a metaclass for this class
def self.metaclass; class << self; self; end; end

私は Ruby に詳しくありませんが、これを拡張するとどうなるでしょうか。

def self.metaclass
    def self.self
    end
end

少なくとも私はそう理解しています。ただし、このコードが何をするのかはまだ正確には理解されていません。その目的は何ですか?

コードのさらに先に、Why がこれを追加します。

arr.each do |a|
   metaclass.instance_eval do
     define_method( a ) do |val|
       @traits ||= {}
       @traits[a] = val
     end
   end
 end

私が正しく理解している場合、このコードは、指定された名前と値で @traits に新しい値を追加します。あれは正しいですか?

助けてくれてありがとう。見たい人のために、私に問題を引き起こした完全なソースコードを以下に示します。

# The guts of life force within Dwemthy's Array
class Creature

# Get a metaclass for this class
def self.metaclass; class << self; self; end; end

# Advanced metaprogramming code for nice, clean traits
def self.traits( *arr )
 return @traits if arr.empty?

 # 1. Set up accessors for each variable
 attr_accessor *arr

 # 2. Add a new class method to for each trait.
 arr.each do |a|
   metaclass.instance_eval do
     define_method( a ) do |val|
       @traits ||= {}
       @traits[a] = val
     end
   end
 end

 # 3. For each monster, the `initialize' method
 #    should use the default number for each trait.
 class_eval do
   define_method( :initialize ) do
     self.class.traits.each do |k,v|
       instance_variable_set("@#{k}", v)
     end
   end
 end

end

# Creature attributes are read-only
traits :life, :strength, :charisma, :weapon
end

そして使用中:

class Dragon < Creature
    life( 1340 )     # tough scales
    strength( 451 )  # bristling veins
    charisma( 1020 ) # toothy smile
    weapon( 939 )    # fire breath
end
4

2 に答える 2

5
class Foo
  def self.bar    # Create a method invoked by Foo.bar instead of Foo.new.bar
    42            # the return value of this method (value of last expression)
  end
end


class Foo
  def self.jim    # Another method on the class itself
    class << self # Change the 'self' to be the metaclass of the current object
      self        # Evaluate the current 'self' as the 'return value' of 
    end           # class<<self…end; and since this is the last expression in
  end             # the method, its value is the return value for the method
end

要するに、あなたが見ているのはmetaclassCreatureクラス自体で名前が付けられたメソッドを定義しています(インスタンスではありません)。このメソッドを実行すると、メタクラスが検出され、それがCreature返されます。

オブジェクトの「メタクラス」とは何かについては、ネットを読んでください。

于 2012-04-11T03:25:08.393 に答える
2

展開された形式では、まったく同じように見えます。

def self.metaclass
  class << self
    self
  end
end

を返すだけであることに注意してください。これはself、実際にはメタクラスであるメタクラスのコンテキスト内で評価されるためです。class << selfself

define_singleton_methodなどの導入により、メタクラスに直接アクセスする必要があるケースは非常に少なくなりました。

これはすべて非常に複雑で、「すべてがオブジェクトである」という設計原則の結果のようです。

于 2012-04-11T03:30:49.697 に答える