3

私はRubyスターターです。これらは両方とも(出力で)非常に似ていることがわかりましたが、以下のコンテキストでの違いを理解できませんでした。たとえば、私はクラスを持っています

class Say
  def self.hello
    puts "hello"
  end
end

このように拡張できます

class << Say
  def hi
    puts "hi"
  end
end

そしてまたこのように

Say.class_eval do
  def self.bye
    puts "bye"
  end
end

<<いつ、いつ使用する必要がありclass_evalますか?

4

2 に答える 2

15

class_evalとは実際には何の関係もありませんclass << className

A.class_eval do
   ...
end

と同等です

class A
  ...
end

いくつかの違いがあります。class_evalはブロック(または文字列ですが、現時点ではそれを無視します)を使用します。これは、含まれている字句スコープを閉じることを意味します。つまり、周囲のスコープのローカル変数を使用できます。共通クラスブロックは、まったく新しいスコープを導入します。同様に、ブロックを作成して多くの異なるclass_evalに渡すことができ、ブロックの本体は、class_evalを呼び出しているクラスのコンテキストで実行されます。

class << classNameのシングルトンクラスを開き、classNameクラスメソッドを定義できるようにします。

class << A
  def foo
    ...
  end
end

と同じです

def A.foo
  ...
end

Aが(ほぼ)クラスである場合、それらはolyクラスメソッドであることに注意してください。rubyのすべてのオブジェクトはシングルトンクラスを持ち、これら2つの構文のいずれかを使用してそれらのメソッドを定義できます。の利点は、class << obj主に、一度に多くのシングルトンメソッドを定義する場合です。

于 2011-03-22T13:31:59.070 に答える
1

すでに述べたように、class_evalは実際にはあまり関係がありません

class <<self

あなたの例では同じことをしているように見えても(効果は似ていますが、同じことはしませんが、微妙な違いがあります)。

2番目の形式の使用法がはるかに明確である別の例を次に示します。

class A

end


a = A.new
b = A.new

class <<b
  def say_hi
    puts "Hi !"
  end
end


b.say_hi # will print "Hi !"
a.say_hi # will raise an undefined method

aとbはどちらも同じクラスAのオブジェクトですが、bのメタクラスにメソッドを追加したため、メソッドsay_hiはbオブジェクトでのみ使用できます。

于 2011-03-22T14:04:35.330 に答える