Подтвердить что ты не робот

Что такое класс singleton в рубине?

Кажется, что мне не хватает смысла или непонимания значения класса singleton в Ruby. Я слышал и читал об этом по-разному - что-то более сложное, чем другие, но я больше смущен тем, что это такое. Это класс сам по себе? Это причина, по которой все объекты принадлежат классу? Концепция нечеткая, но я считаю, что она имеет какое-то отношение к тому, почему я могу вообще определить метод класса (класс foo; def foo.bar...).

Итак: Каков класс singleton в Ruby?

4b9b3361

Ответ 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