수색…


통사론

  • singleton_class = 클래스 << 객체; 자기 끝

비고

싱글 톤 클래스는 하나의 인스턴스 만 갖습니다 : 해당 객체. 이것은 Ruby의 ObjectSpace 를 쿼리하여 확인할 수 있습니다.

instances = ObjectSpace.each_object object.singleton_class

instances.count            # => 1
instances.include? object  # => true

< 사용하면 객체의 실제 클래스의 하위 클래스로도 확인할 수 있습니다.

object.singleton_class < object.class  # => true

참고 문헌 :

소개

Ruby에는 세 가지 유형의 객체가 있습니다.

  • Class 클래스 또는 Class 모듈의 인스턴스 인 클래스 및 모듈입니다.
  • 클래스의 인스턴스.
  • 싱글 톤 클래스.

각 객체에는 해당 메소드가 포함 된 클래스가 있습니다.

class Example
end

object = Example.new

object.class  # => Example
Example.class # => Class
Class.class   # => Class

객체 자체는 메소드를 포함 할 수 없으며 클래스 만이 사용할 수 있습니다. 그러나 싱글 톤 클래스를 사용하면 다른 싱글 톤 클래스를 포함한 모든 객체에 메소드를 추가 할 수 있습니다.

def object.foo
  :foo
end
object.foo #=> :foo

fooobject 싱글 톤 클래스에서 정의됩니다. 다른 Example 인스턴스는 foo 응답 할 수 없습니다.

Ruby는 필요에 따라 싱글 톤 클래스를 생성합니다. 그것들에 접근하거나 그것들에 메소드를 추가하면 루비가 그것을 생성합니다.

싱글 톤 클래스에 액세스하기

객체의 싱글 톤 클래스를 얻는 방법에는 두 가지가 있습니다.

  • singleton_class 메소드.
  • 객체의 싱글 톤 클래스를 다시 열고 self 반환합니다.
object.singleton_class

singleton_class = class << object
  self
end

싱글 톤 클래스의 인스턴스 / 클래스 변수 액세스

싱글 톤 클래스는 인스턴스 / 클래스 변수를 객체와 공유합니다.

class Example
  @@foo = :example
end

def Example.foo
  class_variable_get :@@foo
end

Example.foo #=> :example

class Example
  def initialize
    @foo = 1
  end

  def foo
    @foo
  end
end

e = Example.new

e.instance_eval <<-BLOCK
  def self.increase_foo
    @foo += 1
  end
BLOCK

e.increase_foo
e.foo #=> 2

블록은 인스턴스 / 클래스 변수 대상 주변을 닫습니다. class_eval 또는 instance_eval 의 블록을 사용하여 인스턴스 또는 클래스 변수에 액세스하는 것은 불가능합니다. 문자열을 class_eval 전달하거나 class_variable_get 사용하면 문제가 해결됩니다.

class Foo
  @@foo = :foo
end

class Example
  @@foo = :example 

  Foo.define_singleton_method :foo do
    @@foo
  end
end

Foo.foo #=> :example

싱글 톤 클래스의 상속

서브 클래스 서브 클래스도 싱글 톤 클래스

class Example
end

Example.singleton_class #=> #<Class:Example>

def Example.foo
  :example
end

class SubExample < Example
end

SubExample.foo #=> :example

SubExample.singleton_class.superclass #=> #<Class:Example>

모듈 확장 또는 포함은 싱글 톤 클래스를 확장하지 않습니다.

module ExampleModule
end

def ExampleModule.foo
  :foo
end

class Example
  extend ExampleModule
  include ExampleModule
end

Example.foo #=> NoMethodError: undefined method

싱글 톤 클래스를 사용한 메시지 전파

인스턴스에는 데이터를 전달하는 메소드 만 포함되지 않습니다. 그러나 클래스의 인스턴스를 포함한 모든 객체에 대해 싱글 톤 클래스를 정의 할 수 있습니다.

메시지가 객체에 전달되면 (메소드가 호출 될 때) 루비는 먼저 그 객체에 대해 싱글 톤 클래스가 정의되어 있는지 확인하고, 그렇지 않으면 해당 메시지에 응답 할 수 있는지 확인합니다. 그렇지 않으면 루비는 인스턴스의 클래스 '조상 체인을 검사하고이를 처리합니다.

class Example
  def foo
    :example
  end
end

Example.new.foo #=> :example

module PrependedModule
  def foo
    :prepend
  end
end

class Example
  prepend PrependedModule
end

Example.ancestors #=> [Prepended, Example, Object, Kernel, BasicObject]
e = Example.new
e.foo #=> :prepended

def e.foo
  :singleton
end

e.foo #=> :singleton

재개 (원숭이 패치) 싱글 톤 클래스

싱글 톤 클래스를 다시 여는 세 가지 방법이 있습니다.

  • 싱글 톤 클래스에서 class_eval 사용하기.
  • class << 블록 사용.
  • def 를 사용하여 객체의 싱글 톤 클래스에 직접 메소드 정의
class Example
end

Example.singleton_class.class_eval do
  def foo
    :foo
  end
end

Example.foo #=> :foo

class Example
end

class << Example
  def bar
    :bar
  end
end

Example.bar #=> :bar

class Example
end

def Example.baz
  :baz
end

Example.baz #=> :baz

모든 객체에는 액세스 할 수있는 싱글 톤 클래스가 있습니다.

class Example
end
ex1 = Example.new
def ex1.foobar
  :foobar
end
ex1.foobar #=> :foobar

ex2 = Example.new
ex2.foobar #=> NoMethodError

싱글 톤 클래스

모든 객체는 클래스의 인스턴스입니다. 그러나 그것은 모든 진실이 아닙니다. Ruby에서 모든 객체는 또한 다소 숨겨진 싱글 톤 클래스를 가지고 있습니다.

이것이 개별 객체에 메서드를 정의 할 수있게합니다. 싱글 톤 클래스는 객체 자체와 실제 클래스 사이에 위치하므로 정의 된 모든 메소드는 해당 객체와 해당 객체에서만 사용할 수 있습니다.

object = Object.new

def object.exclusive_method
  'Only this object will respond to this method'
end

object.exclusive_method
# => "Only this object will respond to this method"

Object.new.exclusive_method rescue $!
# => #<NoMethodError: undefined method `exclusive_method' for #<Object:0xa17b77c>>

위의 예제는 define_singleton_method 사용하여 작성되었을 수 있습니다.

object.define_singleton_method :exclusive_method do
  "The method is actually defined in the object's singleton class"
end

objectsingleton_class 에 대해 메소드를 정의하는 것과 같습니다 :

# send is used because define_method is private
object.singleton_class.send :define_method, :exclusive_method do
  "Now we're defining an instance method directly on the singleton class"
end

Ruby의 핵심 API의 일부로 singleton_class 가 존재하기 전에 싱글 톤 클래스는 메타 클래스로 알려져 있었으며 다음 관용구를 통해 액세스 할 수있었습니다.

class << object
  self  # refers to object's singleton_class
end


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow