web-dev-qa-db-ja.com

クラス<< Rubyの自己熟語

class << selfはRubyで何をするの?

803
randombits

まず、class << foo構文はfooのシングルトンクラス(固有クラス)を開きます。これにより、その特定のオブジェクトで呼び出されるメソッドの動作を特殊化できます。

a = 'foo'
class << a
  def inspect
    '"bar"'
  end
end
a.inspect   # => "bar"

a = 'foo'   # new object, new singleton class
a.inspect   # => "foo"

ここで、質問に答えるために:class << selfselfのシングルトンクラスを開き、メソッドが現在のselfオブジェクト(クラスまたはモジュール本体内でクラスまたはモジュールである)に対して再定義できるようにしますそれ自体)。通常、これはクラス/モジュール(「静的」)メソッドを定義するために使用されます。

class String
  class << self
    def value_of obj
      obj.to_s
    end
  end
end

String.value_of 42   # => "42"

これは略記として書くこともできます:

class String
  def self.value_of obj
    obj.to_s
  end
end

またはさらに短く:

def String.value_of obj
  obj.to_s
end

関数定義内では、selfは関数が呼び出されるオブジェクトを参照します。この場合、class << selfはそのオブジェクトのシングルトンクラスを開きます。その使用法の1つは、貧乏人の状態マシンを実装することです。

class StateMachineExample
  def process obj
    process_hook obj
  end

private
  def process_state_1 obj
    # ...
    class << self
      alias process_hook process_state_2
    end
  end

  def process_state_2 obj
    # ...
    class << self
      alias process_hook process_state_1
    end
  end

  # Set up initial state
  alias process_hook process_state_1
end

したがって、上記の例では、StateMachineExampleの各インスタンスはprocess_hookにエイリアスされたprocess_state_1を持っていますが、後者ではprocess_hookを再定義できることに注意してください(selfのみ、他のStateMachineExampleインスタンスに影響しない)からprocess_state_2へ。そのため、呼び出し元がprocessメソッド(再定義可能なprocess_hookを呼び出す)を呼び出すたびに、その状態に応じて動作が変わります。

865

私はこの ブログclass << selfEigenclass、および異なるタイプのmethodsに関する非常に単純な説明を見つけました。

Rubyでは、クラスに適用できるメソッドは3種類あります。

  1. インスタンスメソッド
  2. シングルトン法
  3. クラスメソッド

インスタンスメソッドとクラスメソッドは、他のプログラミング言語での同名のメソッドとほとんど同じです。

class Foo  
  def an_instance_method  
    puts "I am an instance method"  
  end  
  def self.a_class_method  
    puts "I am a class method"  
  end  
end

foo = Foo.new

def foo.a_singleton_method
  puts "I am a singletone method"
end

Eigenclass(シングルトンメソッドを含む)にアクセスするもう1つの方法は、次の構文(class <<)を使用することです。

foo = Foo.new

class << foo
  def a_singleton_method
    puts "I am a singleton method"
  end
end

これで、selfのシングルトンメソッドを定義できます。これは、このコンテキストではクラスFoo自体です。

class Foo
  class << self
    def a_singleton_and_class_method
      puts "I am a singleton method for self and a class method for Foo"
    end
  end
end
28
Saman Mohamadi

通常、インスタンスメソッドはグローバルメソッドです。それは、それらが定義されたクラスのすべてのインスタンスでそれらが利用可能であることを意味します。対照的に、シングルトンメソッドは単一のオブジェクトに実装されています。

Rubyはメソッドをクラスに格納し、すべてのメソッドはクラスに関連付けられなければなりません。シングルトンメソッドが定義されているオブジェクトはクラスではありません(これはクラスのインスタンスです)。クラスだけがメソッドを格納できる場合、オブジェクトはシングルトンメソッドをどのように格納できますか?シングルトンメソッドが作成されると、Rubyはそのメソッドを格納するための匿名クラスを自動的に作成します。これらの無名クラスはメタクラスと呼ばれ、シングルトンクラスまたはエイジクラスとしても知られています。シングルトンメソッドはメタクラスに関連付けられており、メタクラスはシングルトンメソッドが定義されているオブジェクトに関連付けられています。

単一のオブジェクト内に複数のシングルトンメソッドが定義されている場合、それらはすべて同じメタクラスに格納されます。

class Zen
end

z1 = Zen.new
z2 = Zen.new

class << z1
  def say_hello
    puts "Hello!"
  end
end

z1.say_hello    # Output: Hello!
z2.say_hello    # Output: NoMethodError: undefined method `say_hello'…

上記の例では、クラス<< z1は現在の自己をz1オブジェクトのメタクラスを指すように変更します。次に、メタクラス内でsay_helloメソッドを定義します。

クラスはオブジェクト(Classという組み込みクラスのインスタンス)でもあります。クラスメソッドは、クラスオブジェクトに関連付けられたシングルトンメソッドに他なりません。

class Zabuton
  class << self
    def stuff
      puts "Stuffing zabuton…"
    end
  end
end

すべてのオブジェクトはメタクラスを持つことができます。つまり、クラスはメタクラスも持つことができます。上記の例では、class << selfはselfを変更してZabutonクラスのメタクラスを指すようにします。メソッドが明示的なレシーバ(メソッドが定義されるクラス/オブジェクト)なしで定義されている場合、それは現在のスコープ内、つまりselfの現在の値内で暗黙的に定義されます。したがって、stuffメソッドはZabutonクラスのメタクラス内で定義されています。上記の例は、クラスメソッドを定義するための別の方法です。私見、それはコードを理解しやすくするので、クラスメソッドを定義するためにdef self.my_new_clas_method構文を使用する方が良いです。上記の例は含まれているので、クラス<< selfの構文に出くわしたときに何が起こっているのか理解できます。

Ruby Classesに関する追加情報は この投稿で見つけることができます

18
BrunoFacca

どのようなクラス<<ものがあります:

class Hi
  self #=> Hi
  class << self #same as 'class << Hi'
    self #=> #<Class:Hi>
    self == Hi.singleton_class #=> true
  end
end

[そのブロックの文脈でself == thing.singleton_classにする]


Thing.singleton_classとは何ですか?

hi = String.new
def hi.a
end

hi.class.instance_methods.include? :a #=> false
hi.singleton_class.instance_methods.include? :a #=> true

hiオブジェクトは、その#methodsからその#singleton_class.instance_methodsを継承し、次にその#class.instance_methodsから継承します。
ここではhiシングルトンクラスインスタンスメソッド:aを与えました。代わりにクラス<< hiを使用して行った可能性があります。
hi#singleton_classはすべてのインスタンスメソッドを持っていますhi#class、そしておそらくそれ以上のもの(ここでは:a)。

[thingのインスタンスメソッド#class#singleton_classのインスタンスメソッドは、thingに直接適用できます。 Rubyがthing.aを見たとき、まずそれを探します:thing.singleton_class.instance_methodsの中の、そしてそれからthing.class.instance_methodsの中のメソッド定義]


ところで - 彼らはオブジェクトのシングルトンクラス==メタクラス==eigenclass.

13
lakesare

Аシングルトンメソッドは、単一のオブジェクトに対してのみ定義されるメソッドです。

例:

class SomeClass
  class << self
    def test
    end
  end
end

test_obj = SomeClass.new

def test_obj.test_2
end

class << test_obj
  def test_3
  end
end

puts "Singleton's methods of SomeClass"
puts SomeClass.singleton_methods
puts '------------------------------------------'
puts "Singleton's methods of test_obj"
puts test_obj.singleton_methods

シングルトンのSomeClassメソッド

テスト


シングルトンのtest_objメソッド

test_2

test_3

3
artamonovdev

実際にあなたのRubyプロジェクトのためにC拡張を書くなら、Moduleメソッドを定義する唯一の方法があります。

rb_define_singleton_method

私はこの自営業が他のあらゆる種類の質問を開くだけであることを知っているので、あなたはそれぞれの部分を検索することによってよりよくすることができました。

最初にオブジェクト。

foo = Object.new

Foo用のメソッドを作ることができますか?

もちろん

def foo.hello
 'hello'
end

私はそれで何をしますか?

foo.hello
 ==>"hello"

もう一つのオブジェクト。

foo.methods

あなたはすべてのObjectメソッドとあなたの新しいものを手に入れる。

def foo.self
 self
end

foo.self

ただのfooオブジェクト。

ClassやModuleのような他のオブジェクトからfooを作ったらどうなるか見てみてください。すべての答えの例はうまくいきますが、コードの作成方法で何が起こっているのかを実際に理解するには、さまざまなアイデアや概念を扱う必要があります。だから今あなたは見に行くための用語がたくさんあります。

Singleton、Class、Module、self、Object、そしてEigenclassが登場しましたが、RubyはそのようにObject Modelsを名付けていません。それはメタクラスのようなものです。 Richardか__whyがあなたにここでその考えを示しています。 http://viewsourcecode.org/why/hacking/seeingMetaclassesClearly.html そしてもしあなたがいなくなったら、Ruby Object Modelを検索してみてください。私がYouTubeで知っている2つのビデオは、Dave ThomasとPeter Cooperです。彼らはその概念も説明しようとしています。それを取得するのに長い時間がかかりましたので心配しないでください。私はまだそれに取り組んでいます。他になぜ私はここにいるのでしょうか?ご質問ありがとうございます。標準ライブラリも見てください。それはちょうどFYIとしてシングルトンモジュールを持っています。

これはかなり良いです。 https://www.youtube.com/watch?v=i4uiyWA8eFk

1