Ruby Language
싱글 톤 클래스
수색…
통사론
- 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
foo
는 object
싱글 톤 클래스에서 정의됩니다. 다른 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
object
의 singleton_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