Разница между «self.method_name» и «class << self» в Ruby - PullRequest
5 голосов
/ 08 января 2010

Я пытался ограничить создание экземпляра одного класса (без использования синглтона), но не смог. Я пытался с переменными класса (@@), но без удачи. Я погуглил и наткнулся на это:

class A 
  @count = 0 

  class << self 
    attr_accessor :count 
  end

  def initialize val 
    @a = val 
    self.class.count += 1 
  end 
end 

a=A.new 42 
b=A.new 43

Я искал объяснение 'class << self </strong>', надеясь найти лучшее (или просто более простое и чистое), но опять же, не повезло. Наконец, после некоторых тестов я пришел к выводу, что 'class << self </strong>' - это просто оболочка блока, в которой вы можете определить class методы. Итак, это правильно?

Привет!

Ответы [ 4 ]

34 голосов
/ 08 января 2010

Запись class << self открывает собственный класс объекта. Собственный класс - это анонимный класс, который хранит специфичное для экземпляра поведение. В случае класса собственный класс иногда называют метаклассом.

Ruby использует собственные классы для реализации так называемых «методов класса» (также называемых статическими методами).

Класс (как сказал Мориц) также является объектом в Ruby, и, поскольку он является объектом, он также имеет класс. Класс класса в Ruby называется Class.

«Метод класса» в любом языке - это метод, в котором класс является получателем, то есть метод вызывается непосредственно для самого класса.

Однако, чтобы метод вызывался для получателя, этот метод должен быть определен в классе этого получателя. В случае классов «метод класса» может быть реализован как метод экземпляра класса Class.

Но определение метода экземпляра на Class будет означать, что ВСЕ классы получают доступ к этому методу класса, который не идеален.

Введите собственный класс, как указано выше, собственный класс для объекта - это специальный класс, в котором хранятся методы, уникальные для этого объекта. В случае классов подклассы собственного класса относятся к классу Class и являются прямым классом класса.

«методы класса» в Ruby являются просто «методами экземпляра», определенными в собственном классе класса.

Запись def MyClass.my_method фактически определяет my_method для собственного класса MyClass. Если вы используете эту нотацию, вы можете обойтись (на некоторое время), фактически не понимая собственных классов, поскольку вы можете обмануть себя, думая, что это просто способ определения «статических методов» в Ruby, и продолжайте думать, что модель классов Ruby похожа на модель Java. Однако запись class << self не допускает такой интерпретации, и вы должны смириться с реальностью собственных классов.

Таким образом, «методы класса» на самом деле являются «методами экземпляра», определенными в собственном классе, а class << self предоставляет вам доступ к собственному классу.

Для получения дополнительной информации ознакомьтесь со следующими ссылками:

http://banisterfiend.wordpress.com/2008/11/25/a-complete-ruby-class-diagram/

http://banisterfiend.wordpress.com/2008/10/25/the-secret-life-of-singletons/

http://www.klankboomklang.com/2007/09/21/the-singleton-class/

5 голосов
/ 08 января 2010

Технически вы определяете метод для метакласса класса, а не для самого класса. У Иегуды Каца есть отличное объяснение метаклассов в Ruby здесь:

2 голосов
/ 19 февраля 2012

Строка темы не совсем соответствует основной части вопроса. Я собираюсь ответить на вопрос, выраженный в строке темы :

Они являются синонимами.

def self.foo
    ...
end

это просто сокращение для

class << self
    def foo
        ...
    end
end
2 голосов
/ 08 января 2010

Ваш вывод верен. По сути, вы должны иметь в виду, что даже классы являются объектами в ruby ​​и, следовательно, имеют экземпляры. И с оператором класса << self вы просто изменяете этот экземпляр класса вашего объекта. </p>

...