В Ruby, в контексте метода класса, что такое переменные экземпляра и класса?

Если у меня есть следующий фрагмент кода Ruby:

class Blah
  def self.bleh
    @blih = "Hello"
    @@bloh = "World"
  end
end

Что такое @blih и @@bloh? @blih — это переменная экземпляра класса Blah, а @@bloh — переменная класса класса Blah, верно? Означает ли это, что @@bloh является переменной в классе Бла, Class?


person pupeno    schedule 08.04.2010    source источник


Ответы (4)


Кажется, что люди игнорируют тот факт, что метод является методом класса.

@blih будет переменной экземпляра экземпляра класса Class для константы Bleh. Следовательно:

irb(main):001:0> class Bleh
irb(main):002:1>   def self.bleh
irb(main):003:2>     @blih = "Hello"
irb(main):004:2>     @@blah = "World"
irb(main):005:2>   end
irb(main):006:1> end
=> nil
irb(main):007:0> Bleh.instance_variables
=> []
irb(main):008:0> Bleh.bleh
=> "World"
irb(main):009:0> Bleh.instance_variables
=> ["@blih"]
irb(main):010:0> Bleh.instance_variable_get :@blih
=> "Hello"

@@blah будет доступен как переменная класса Bleh:

irb(main):017:0> Bleh.class_variables
=> ["@@blah"]
irb(main):018:0> Bleh.send :class_variable_get, :@@blah
=> "World"
person user253455    schedule 08.04.2010

У этого безумия есть метод...

class Example
  @foo # class instance variable
  @@bar # class variable

  def fun1
    @baz # instance variable
  end
end

Переменные экземпляра

Переменные экземпляра (в примере @foo и @baz) всегда начинаются с @ и они всегда принадлежат любому объекту, на который ссылается self: либо объекту класса, либо классу объект, представляющий класс. Ссылка на переменную экземпляра в определении класса или методе класса полностью отличается от ссылки на переменную экземпляра в методе экземпляра.

Наследование
Поскольку переменные экземпляра не определяются классом, они не связаны с механизмом наследования — они просто создаются, когда им присваивается значение. Таким образом, переменные экземпляра класса, будучи просто переменными экземпляра объекта класса, представляющего класс, не наследуются.

Переменные класса

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

Переменная экземпляра класса против переменной экземпляра

Недостатком переменных экземпляра класса является то, что их нельзя использовать в методах экземпляра, как это могут делать переменные класса. Другим недостатком является возможность спутать их с обычными переменными экземпляра. Преимущество переменных экземпляра класса над переменными класса связано с запутанным поведением переменных класса при создании подкласса существующего класса: если класс использует переменные класса, то любой подкласс может изменить поведение класса и всех его потомков, изменив значение общей переменной класса. Это сильный аргумент в пользу использования переменных экземпляра класса вместо переменных класса.

Многое из этого взято из отличного "Язык программирования Ruby"
альтернативный текст

person JRL    schedule 08.04.2010
comment
@banister: я склонен не соглашаться. Я думаю, что я специально ответил на вопрос двумя предложениями, выделенными жирным шрифтом. Я мог бы просто поставить эти утверждения без остального, но я думаю, что это было бы менее полезно. В любом случае, это только мое мнение. - person JRL; 08.04.2010

Переменная с префиксом из двух знаков at является переменной класса, доступной как в методах экземпляра, так и в методах класса класса.

Пример:

class CountEm
  @@children = 0

  def initialize
    @@children += 1
    @myNumber = @@children
  end

  def whoAmI
    "I'm child number #@myNumber (out of #@@children)"
  end

  def CountEm.totalChildren
    @@children
  end
end

c1 = CountEm.new
c2 = CountEm.new
c3 = CountEm.new
c1.whoAmI              # -> "I'm child number 1 (out of 3)"
c3.whoAmI              # -> "I'm child number 3 (out of 3)"
CountEm.totalChildren  # -> 3

Пример взят из текста ссылки

person Petros    schedule 08.04.2010
comment
ОП понимает, что такое переменные класса, он спрашивает, как они могут измениться при использовании из метода класса. - person Jimmy; 08.04.2010
comment
Я не уверен, но если это так, то прошу прощения. Виноват. - person Petros; 08.04.2010

[отредактировано для ясности]

В вашем примере настройка @blih не будет видна за пределами области вашего метода класса, потому что внутри метода класса нет экземпляра для привязки к нему переменной экземпляра.

Говоря о терминологии, я бы сказал, что «@@bloh — это переменная класса в классе Blah», но не «переменная в классе Class Class». Класс "Класс" остается нетронутым.

person Wojciech Kaczmarek    schedule 08.04.2010
comment
Есть экземпляр, к которому нужно привязаться. Класс является экземпляром класса Class и будет создан при оценке определения класса. › Блех.instance_of? Класс =› правда - person user253455; 08.04.2010
comment
crudson прав, @blih — это переменная экземпляра, присоединенная к классу Blah. - person horseyguy; 08.04.2010