Что такое класс singleton в ruby?


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

Итак: Что это одноэлементный класс в Ruby?

4 59

4 ответа:

во-первых, небольшое определение: a синглтон метод - это метод, который определяется только для одного объекта. Пример:

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 объекта open:

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

в итоге:

  • методы всегда должны принадлежать классу (или: быть методами экземпляра некоторого класса)
  • нормальные методы принадлежат классу они определены в (т. е. являются методами экземпляра класса)
  • методы класса-это просто одноэлементные методы a Class
  • синглтон-методы объекта не являются методами экземпляра класса объекта; скорее, они являются методами экземпляра Singleton-класс объекта.

Ruby предоставляет способ определения методов, специфичных для конкретного объекта, и такие методы известны как одноэлементные методы. Когда объявляется одноэлементный метод для объекта, 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_methods можно вызвать на объект, чтобы получить список имен всех синглтон-методы объекта.

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

этой статьи действительно помог мне понять одноэлементные классы в Ruby, и у него есть хороший пример кода.

наиболее прагматичный / действенный способ думать об этом (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

кроме того, я думаю, что запутанный использование термина "одноэлементный объект", который является другим понятием. Одноэлементный объект происходит из класса, который имеет переопределенный метод конструктора/экземпляра, так что вы можете выделить только один из этого класса.

Как только обновление до ответа @Pistos, из версии 1.9.2 ruby добавьте новый синтаксис для получения одноэлементного класса

 singleton_class = ( class << foo; self; end )

можно заменить на:

singleton_class = foo.singleton_class

https://apidock.com/ruby/Object/singleton_class