루비의 클래스 << 자체 관용구


873

루비class << self 에서 무엇을 합니까?


35
Yehuda Katz가 쓴이 주제에 관한 아주 좋은 기사가 있습니다 : yehudakatz.com/2009/11/15/… 그리고 Yugui : yugui.jp/articles/846
Andrei

3
여기에 또 다른 훌륭한 기사가 있습니다 : integralist.co.uk/posts/eigenclass.html
Saman Mohamadi

2
나는 이것을 모듈 내부에서보고 있는데, 그것이 다른가? github.com/ruby/rake/blob/master/lib/rake/rake_module.rb
William Entriken

@FullDecent Ruby의 모든 것이 모듈과 클래스를 포함한 객체이므로 차이가 없습니다.
Aaron

답변:


912

먼저 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 << self열어 self현재 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해당 객체의 싱글 톤 클래스를 엽니 다. 그 중 하나는 가난한 사람의 상태 머신을 구현하는 것입니다.

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

따라서 위의 예에서의 각 인스턴스는 StateMachineExampleprocess_hook별칭 이 지정되어 process_state_1있지만 후자는 어떻게 다른 인스턴스에 영향을 미치지 않는지에 process_hook대해 재정의 할 수 있습니다 . 따라서 호출자가 메소드를 호출 할 때마다 (재정의 가능을 호출 함 ) 상태에 따라 동작이 변경됩니다.selfStateMachineExampleprocess_state_2processprocess_hook


22
@ Jörg : 편집을 위해 +1 (SO가 편집을 피하는 기능을 제공하기를 바랍니다. 실제로 class << self클래스 / 모듈 메소드를 작성하기 위해 의보다 일반적인 사용입니다 . 나는 class << self훨씬 더 관용적 인 사용법이므로 아마도 그 사용을 확장 할 것입니다 .
Chris Jester-Young

4
gsub! ( "eigenclass", "singleton class"), 다음 방법을 참조하십시오 redmine.ruby-lang.org/repositories/revision/1?rev=27022
Marc-André Lafortune

4
정말에 참조하는 혼란 asingleton_class이후 a의 클래스 (변경 후 '하는 것은 inspect)의 독특한 변종 String클래스입니다. 싱글 톤 String클래스를 변경하는 경우 다른 모든 String인스턴스에 영향을줍니다 . 무엇 아직도 더 이상한 것은 나중에 다시 경우이다 String재정의 inspect한 후 a여전히 새로운 변경 사항을 선택합니다.
Old Pro

1
@OldPro Matz와 마찬가지로 여전히 고유 클래스라는 이름을 선호합니다. 그러나 모든 사람을 기쁘게 할 수는 없습니다.
Chris Jester-Young

5
"이전에 여러 번 읽은" "개체의 싱글 톤 클래스를 연다"라는 표현이 모호합니다. 내가 아는 바에 따르면, 루비 문서의 어느 부분도 정의 된 클래스를 "개방"할 수 없다. 합니까 class << self이상 값보다 평균 아무것도 self블록의 범위 내에서 싱글 톤 클래스에 동일하게 설정되어 있습니까?
캐리 스월 랜드

34

나는 약 슈퍼 간단한 설명을 발견 class << self, Eigenclass및 방법의 다른 유형을.

Ruby에는 클래스에 적용 할 수있는 세 가지 유형의 메소드가 있습니다.

  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(싱글 톤 메서드 포함) 에 액세스하는 다른 방법은 다음 구문 ( 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

4
실제로 싱글 톤 메소드와 클래스 메소드는 동일합니다. 둘 다 싱글 톤 클래스에 존재합니다. foo.singleton_class.instance_methods(false)확인 하는 데 사용할 수 있습니다 .
데이먼 위안

22

일반적으로 인스턴스 메소드는 글로벌 메소드입니다. 즉, 정의 된 클래스의 모든 인스턴스에서 사용할 수 있습니다. 반대로 싱글 톤 방법은 단일 객체에서 구현됩니다.

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 Zabuton
  class << self
    def stuff
      puts "Stuffing zabuton…"
    end
  end
end

모든 객체에는 메타 클래스가있을 수 있습니다. 즉, 클래스에는 메타 클래스도있을 수 있습니다. 위의 예에서 class << self는 self를 수정하여 Zabuton 클래스의 메타 클래스를 가리 킵니다. 명시 적 수신자 (메소드가 정의 될 클래스 / 객체)없이 메소드가 정의되면, 현재 범위, 즉 현재 자체 값 내에 내재적으로 정의됩니다. 따라서 stuff 메소드는 Zabuton 클래스의 메타 클래스 내에 정의됩니다. 위의 예제는 클래스 메소드를 정의하는 또 다른 방법입니다. IMHO, def self.my_new_clas_method 구문을 사용하여 코드를 이해하기 쉽도록 클래스 메소드를 정의하는 것이 좋습니다. 위의 예제는 클래스 << 자체 구문을 접할 때 발생하는 상황을 이해하기 위해 포함되었습니다.

이 게시물 에서 Ruby 클래스에 대한 추가 정보를 찾을 수 있습니다 .


15

어떤 클래스 <<가하는 일 :

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여기).

일의의 [인스턴스 메소드 #class 와는 #singleton_class 일에 직접 적용 할 수 있습니다. 루비가 thing.a를 볼 때, 먼저 : thing.singleton_class.instance_methods에서 메소드 정의를 찾은 다음 thing.class.instance_methods에서 찾습니다.]


그건 그렇고-그들은 객체의 싱글 톤 클래스 == metaclass == eigenclass라고 부릅니다 .


3

А 싱글 방법은 하나의 객체에 대해서만 정의하는 방법이다.

예:

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


1

실제로 Ruby 프로젝트에 대한 C 확장을 작성하는 경우 실제로 모듈 메소드를 정의하는 한 가지 방법 만 있습니다.

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 객체입니다.

클래스 및 모듈과 같은 다른 객체에서 foo를 만들면 어떻게되는지 확인하십시오. 모든 답변의 예는 훌륭하지만 코드 작성 방식에 어떤 일이 일어나고 있는지 실제로 이해하려면 다른 아이디어 나 개념으로 작업해야합니다. 이제 살펴볼 용어가 많이 있습니다.

Singleton, Class, Module, self, Object 및 Eigenclass가 등장했지만 Ruby는 그런 식으로 Object Models의 이름을 지정하지 않습니다. 메타 클래스와 비슷합니다. Richard 또는 __why는 여기서 아이디어를 보여줍니다. http://viewsourcecode.org/why/hacking/seeingMetaclassesClearly.html 그리고 만약 당신이 불면 당신은 검색에서 루비 객체 모델을 찾아보십시오. YouTube에서 내가 아는 두 가지 비디오는 Dave Thomas와 Peter Cooper입니다. 그들은 그 개념도 설명하려고 노력합니다. Dave가 그것을 얻는 데 오랜 시간이 걸렸으므로 걱정하지 마십시오. 나는 아직도 그것을하고 있습니다. 내가 왜 또 왔을 까? 질문 해 주셔서 감사합니다. 또한 표준 라이브러리를 살펴보십시오. FYI와 마찬가지로 싱글 톤 모듈이 있습니다.

이것은 꽤 좋습니다. https://www.youtube.com/watch?v=i4uiyWA8eFk

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.