루비의 싱글 톤 클래스는 정확히 무엇입니까?


85

Ruby의 싱글 톤 클래스는 그 자체로 클래스입니까? 모든 객체가 "클래스"에 속하는 이유입니까? 개념은 모호 하지만 클래스 메서드를 정의 할 수있는 이유 ( class foo; def foo.bar ...) 와 관련이 있다고 생각합니다 .

Ruby의 싱글 톤 클래스는 무엇입니까?

답변:


154

첫째, 약간의 정의 : 싱글 톤 메서드 는 단일 객체에 대해서만 정의되는 메서드입니다. 예:

irb(main):001:0> class Foo; def method1; puts 1; end; end
=> nil
irb(main):002:0> foo = Foo.new
=> #<Foo:0xb79fa724>
irb(main):003:0> def foo.method2; puts 2; end
=> nil
irb(main):004:0> foo.method1
1
=> nil
irb(main):005:0> foo.method2
2
=> nil
irb(main):006:0> other_foo = Foo.new
=> #<Foo:0xb79f0ef4>
irb(main):007:0> other_foo.method1
1
=> nil
irb(main):008:0> other_foo.method2
NoMethodError: undefined method `method2' for #<Foo:0xb79f0ef4>
        from (irb):8

인스턴스 메서드는 클래스의 메서드입니다 (즉, 클래스의 정의에 정의 됨). 클래스 메서드는 클래스의 Class인스턴스 에 대한 단일 메서드 입니다. 클래스 정의에 정의되어 있지 않습니다. 대신 객체 의 싱글 톤 클래스 에 정의됩니다 .

irb(main):009:0> Foo.method_defined? :method1
=> true
irb(main):010:0> Foo.method_defined? :method2
=> false

구문을 사용하여 개체의 단일 클래스를 엽니 다 class << obj. 여기에서이 싱글 톤 클래스가 싱글 톤 메소드가 정의 된 곳임을 알 수 있습니다.

irb(main):012:0> singleton_class = ( class << foo; self; end )
=> #<Class:#<Foo:0xb79fa724>>
irb(main):013:0> singleton_class.method_defined? :method1
=> true
irb(main):014:0> singleton_class.method_defined? :method2
=> true
irb(main):015:0> other_singleton_class = ( class << other_foo; self; end )
=> #<Class:#<Foo:0xb79f0ef4>>
irb(main):016:0> other_singleton_class.method_defined? :method1
=> true
irb(main):017:0> other_singleton_class.method_defined? :method2
=> false

따라서 객체에 싱글 톤 메소드를 추가하는 다른 방법은 객체의 싱글 톤 클래스를 열어서 정의하는 것입니다.

irb(main):018:0> class << foo; def method3; puts 3; end; end
=> nil
irb(main):019:0> foo.method3
3
=> nil
irb(main):022:0> Foo.method_defined? :method3
=> false

요약해서 말하자면:

  • 메서드는 항상 클래스에 속해야합니다 (또는 : 일부 클래스의 인스턴스 메서드 여야 함).
  • 일반 메소드는 정의 된 클래스에 속합니다 (즉, 클래스의 인스턴스 메소드).
  • 클래스 메서드는 Class
  • 개체의 단일 메서드는 개체 클래스의 인스턴스 메서드가 아닙니다. 오히려 객체의 싱글 톤 클래스의 인스턴스 메서드입니다.

17
내 비석에는 "RIP Ruby Singleton. Pistos가 내 정신을 구했습니다."라고 표시됩니다.
rmcsharry

1
@sawa 나는 당신의 편집 의도에 감사하지만 그들이 내 게시물의 의미와 의사 소통을 너무 많이 바꾼 것 같아서 당신의 편집을 롤백했습니다.
Pistos 2019

33

Ruby는 특정 객체에 특정한 메서드를 정의하는 방법을 제공하며 이러한 메서드를 Singleton 메서드라고합니다. 객체에 싱글 톤 메소드를 선언하면 Ruby는 싱글 톤 메소드 만 보유하는 클래스를 자동으로 생성합니다. 새로 생성 된 클래스를 싱글 톤 클래스라고합니다.


    foo = Array.new
    def foo.size
      "Hello World!"
    end
    foo.size  # => "Hello World!"
    foo.class # => Array
    #Create another instance of Array Class and call size method on it
    bar = Array.new
    bar.size  # => 0
Singleton 클래스는 자동으로 생성되어 상속 계층에 삽입되는 객체 별 익명 클래스입니다.

singleton_methods 객체에 대한 모든 싱글 톤 메소드의 이름 목록을 가져 오기 위해 객체에서 호출 될 수 있습니다.

    foo.singleton_methods  # => [:size]
    bar.singleton_methods  # => []

기사 는 Ruby의 Singleton Classes를 이해하는 데 정말 도움 이 되었으며 좋은 코드 예제가 있습니다.


4
이 답변은 1 년이 넘었고 링크가 도움이되지만 여기,이 사이트에 답변의 필수 부분을 게시하거나 게시물이 삭제 될 위험이있는 경우 더 나을 것입니다. '거의 많지 않은 답변'이 언급 된 FAQ를 참조하세요. 링크보다 '. 원하는 경우 링크를 계속 포함 할 수 있지만 '참조'로만 사용할 수 있습니다. 대답은 링크가 필요없이 그 자체로 존재해야합니다.
Taryn

@bluefeet 여기에 동의
Saurabh

감사합니다 @bluefeet, 귀하의 의견을 해결하기 위해 답변을 업데이트했습니다.
Bedasso 2015 년


4

그것을 생각하는 가장 실용적이고 행동 지향적 인 방식 (IMHO)은 상속 체인 또는 메서드 조회 / 해결 순서입니다. 이 사진이 도움이 될 수 있습니다

http://www.klankboomklang.com/2007/11/25/modules-part-i-enter-the-include-class/

이것은 r 1.9로, 내장 및 사용자 정의 클래스와 대조됩니다. 저는 여전히이 클래스를 소화하고 있습니다.

http://d.hatena.ne.jp/sumim/20080111/p1

또한 개념이 다른 "Singleton object"라는 용어의 사용을 혼동스럽게 생각합니다. 싱글 톤 객체는 생성자 / 인스턴스 에이터 메서드가 재정의 된 클래스에서 가져 오므로 해당 클래스 중 하나만 할당 할 수 있습니다.


링크 중 하나가 죽었습니다. 그리고 다른 하나는 일본인입니다!
Ulysse BN

0

가장 간단한 용어로 싱글 톤 클래스는 개별 객체에 정의 된 호스트 메서드에 달하는 특수 클래스 루비입니다. 루비에서는 해당 객체에만 고유 한 개별 객체에 대한 메서드를 정의 할 수 있습니다. 예를 들어 다음을 고려하십시오.

class User; end
user = User.new
def user.age
  "i'm a unique method"
end
user1 = User.new 
user.age #"i'm a unique method"
user1.age # NoMethodError (undefined method `age' for #<User:0x0000559c66ab7338>)

위에서 볼 수 있듯이 user1 객체는 user 객체에 고유하게 정의 된 방법 인 singleton 방법이기 때문에 'age'방법에 응답하지 않습니다. 이를 위해 루비는이 고유 한 메서드를 호스팅하기 위해 단일 클래스 또는 고유 클래스라는 특수 클래스를 만듭니다. 다음을 수행하여이를 확인할 수 있습니다.

user.singleton_class # #<Class:#<User:0x0000559c66b47c58>>

또한 'age'메소드가 정의 된 위치를 찾기 위해 메소드 객체를 사용하여 여기에서 'age'메소드가 있는지 루비에게 물어볼 수 있습니다. 이렇게하면 싱글 톤 클래스에 해당 메서드가 있음을 알 수 있습니다.

user_singleton_class = user.method(:age).owner # #<Class:#<User:0x0000559c66b47c58>>
user.method(:age).owner == user.singleton_class # true
user_singleton_class.instance_methods(false) # [:age]

또한 싱글 톤 클래스가 진행되는 한 싱글 톤 메소드는 실제로 인스턴스 메소드입니다.

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