Что такое синглтон-класс в ruby? - PullRequest
68 голосов
/ 17 октября 2008

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

Что такое синглтон-класс в Ruby?

Ответы [ 4 ]

129 голосов
/ 17 октября 2008

Во-первых, небольшое определение: метод 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

Таким образом, альтернативным способом добавления одноэлементных методов к объекту было бы определение их с открытым одноэлементным классом объекта:

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
  • одноэлементные методы объекта не являются методами экземпляра класса объекта; скорее они являются методами экземпляра синглтон-класса объекта.
23 голосов
/ 20 января 2012

Ruby предоставляет способ определения методов, специфичных для конкретного объекта, и такие методы известны как одноэлементные методы. Когда вы объявляете одноэлементный метод для объекта, Ruby автоматически создает класс для хранения только одноэлементных методов. Вновь созданный класс называется Singleton Class.

<code>
    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 - это специфичный для объекта анонимный класс, который автоматически создается и вставляется в иерархию наследования.

singleton_methods можно вызвать для объекта, чтобы получить список имен для всех одноэлементных методов объекта.

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

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

6 голосов
/ 24 октября 2017

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

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

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

singleton_class = foo.singleton_class

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

4 голосов
/ 17 октября 2008

Наиболее прагматичный / ориентированный на действие способ думать об этом (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» является другим понятием. Объект-одиночка происходит из класса, у которого есть переопределенный метод конструктора / экземпляра, так что вы можете выделить только один из этого класса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...