Ruby: переменные экземпляра класса и переменные экземпляра

Моя идея - создать вики сообщества для людей, которые приходят с фона java, потому что, читая много объяснений, я ничего не мог понять, пока я не попробовал пару вещей, и части головоломки начали найти свои места. Но сначала я должен убедиться, что все правильно. Исходя из этого, мне было очень сложно понять, что @variable может означать две разные вещи. Вот пример:

class Test
  @ins = "gah"
  def self.ins
    puts @ins
  end

  def initialize()
    @ins = "wtf?"
  end
  def ins2
    puts @ins
  end
end

Насколько я понимаю, первая @ins - это переменная экземпляра объекта, представляющего класс Test. Второй @ins является переменной экземпляра в объекте класса Test.

Теперь все начинает иметь для меня какой-то смысл. Вот несколько примеров:

[14] pry(main)> test.ins2
wtf?

Мы вызываем метод объекта и возвращаем переменную экземпляра объекта.

[15] pry(main)> test.ins
NoMethodError: undefined method `ins' for #<Test:0x000000017d9348 @ins="wtf?">

Мы пытаемся вызвать метод класса через объект, этот метод относится к классу, поэтому мы получаем NoMethodError

[16] pry(main)> Test.ins
gah

Мы вызываем метод класса, поэтому он правильно видит переменную экземпляра объекта класса.

[17] pry(main)> Test.ins2
NoMethodError: undefined method `ins2' for Test:Class

Мы вызываем объектный метод через класс, который является неправильным, поэтому бросаем NoMethodError.

Все вышесказанное было выполнено с рубином 2.0. Так что я спрашиваю?

  • Я правильно понял?
  • Я получаю правильную терминологию Ruby?
  • Любое реальное использование переменных экземпляра класса, которое имеет смысл в правильно спроектированном приложении? Или это просто лучшие переменные класса @@?

Ответ 1

мне было очень сложно понять, что @variable может означать две очень разные вещи.

Нет, это не так. Классы - это объекты, подобные любому другому объекту. Они могут иметь переменные экземпляра, как и любой другой объект. Они могут иметь методы экземпляра, как и любой другой объект. Фактически, в отличие от Java, который имеет три разных типа "методов" (методы экземпляра, статические методы и конструкторы), в Ruby существует только один вид метода: методы экземпляра.

Красота того, что классы являются объектами, заключается в том, что @variable всегда означает точно одно и то же.

Нет такой вещи, как переменная экземпляра класса: это просто нормальная переменная экземпляра, как и любая другая. Объект является экземпляром Class, но это не изменяет характер переменной экземпляра. Переменная экземпляра объекта класса String не является переменной экземпляра строки, это просто переменная экземпляра. Аналогично, переменная экземпляра объекта класса Class является просто переменной экземпляра.

Нет такой вещи, как метод класса: это просто обычный одноэлементный метод объекта, который является экземпляром Class. (На самом деле нет такой вещи, как одноэлементный метод: это просто метод обычного экземпляра класса Singleton класса.)

Примечание. Рубисты могут использовать термин "метод класса" в случайном разговоре. Но это не означает, что методы класса фактически существуют, это означает только то, что "метод экземпляра класса Singleton class class" является глотком. Важно то, что поскольку классы являются объектами, они работают точно так же, как и все другие объекты. Они могут иметь методы экземпляра (определенные в классе Class или унаследованные от Module, Object, Kernel или BasicObject), они могут иметь "однотонные методы" (которые действительно являются примерами методов их соответствующих одноэлементных классов), они могут иметь переменные экземпляра.

Они также могут иметь переменные класса (@@variables)... это странно. Игнорировать их: -)

Ответ 2

  • Во-первых, чтобы понять переменные экземпляра, нужно знать это - классы - это объекты.

    Все классы являются экземплярами Class (читайте документ), который наследует от Object. Вот почему классы - это объекты.

  • Затем все переменные экземпляра (идентификаторы, отмеченные @, например @ins) определены в self.

    Когда self является классом, они являются переменными экземпляра классов (переменные экземпляра класса). Когда self является объектом, это переменные экземпляра объектов (переменные экземпляра).

  • В разных областях кода self представляет разные вещи.

    class Test
      # class scope, uncomment following line to see the value of self
      # p self
      @ins = "gah"
      def self.ins
        # class scope
        # p self
        puts @ins
      end
    
      def initialize()
        # object scope
        # p self
        @ins = "wtf?"
      end
      def ins2
        # object scope
        # p self
        puts @ins
      end
    end
    

Ответ 3

Все выглядит правильно для меня.

Переменная класса будет передана через наследование, а переменная экземпляра в классе не будет. (src: переменная экземпляра класса Ruby и переменная класса)

Что касается дизайна, я предпочитаю избегать переменных класса вообще (я бы предпочел использовать singleton), но если бы мне пришлось выбирать один, я бы, вероятно, выбрал переменную класса над переменной экземпляра класса, чтобы избежать путаницы.