Что такое класс singleton в рубине?
Кажется, что мне не хватает смысла или непонимания значения класса singleton в Ruby. Я слышал и читал об этом по-разному - что-то более сложное, чем другие, но я больше смущен тем, что это такое. Это класс сам по себе? Это причина, по которой все объекты принадлежат классу? Концепция нечеткая, но я считаю, что она имеет какое-то отношение к тому, почему я могу вообще определить метод класса (класс foo; def foo.bar...).
Итак: Каков класс singleton в Ruby?
Ответы
Ответ 1
Во-первых, небольшое определение: метод singleton - это метод, который определяется только для одного объекта. Пример:
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
Таким образом, альтернативным способом добавления методов Singleton к объекту было бы определить их с открытым классом Singleton:
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
- Одиночные методы объекта не являются методами экземпляра класса объекта; Скорее, они являются экземплярами одноэлементного класса объекта.
Ответ 2
Ruby предоставляет способ определения методов, специфичных для конкретного объекта, и такие методы известны как методы Singleton. Когда кто-то объявляет однотонный метод для объекта, Ruby автоматически создает класс для хранения только методов singleton. Недавно созданный класс называется Singleton Class.
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 class is object specific anonymous class that is automatically created and inserted into the inheritance hierarchy.
singleton_methods
может быть вызван на объект, чтобы получить список имен для всех методов singleton для объекта.
foo.singleton_methods # => [:size]
bar.singleton_methods # => []
Этот article действительно помог мне разобраться в Singleton Classes в Ruby, и у него хороший пример кода.
Ответ 3
Самый прагматичный/ориентированный на действие способ думать об этом (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", что является другим понятием. Объект singleton исходит из класса, у которого переопределяется его метод constructor/instantiator, так что вы можете выделить только один из этого класса.
Ответ 4
Как только обновление до ответа @Pistos, из версии 1.9.2 ruby добавьте новый синтаксис для получения класса singleton
singleton_class = ( class << foo; self; end )
можно заменить на:
singleton_class = foo.singleton_class
https://apidock.com/ruby/Object/singleton_class