Переменные экземпляра модуля совместно используются классом с миксином? - PullRequest
9 голосов
/ 23 февраля 2012

Я хочу знать, как переменные экземпляра модуля Ruby ведут себя в нескольких классах, которые «смешивают» его «в».Я написал пример кода для тестирования:

# Here is a module I created with one instance variable and two instance methods.
module SharedVar
  @color = 'red'
  def change_color(new_color)
    @color = new_color
  end
  def show_color
    puts @color
  end
end

class Example1
  include SharedVar
  def initialize(name)
    @name     = name
  end
end

class Example2
  include SharedVar
  def initialize(name)
    @name     = name
  end
end

ex1 = Example1.new("Bicylops")
ex2 = Example2.new("Cool")

# There is neither output or complains about the following method call.
ex1.show_color
ex1.change_color('black')
ex2.show_color

Почему это не работает?И может ли кто-нибудь объяснить, каково будет действительное поведение @color в нескольких Example$ экземплярах?

Ответы [ 2 ]

11 голосов
/ 23 февраля 2012

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

module Test
  @test = 'red'
  def self.print_test
    puts @test
  end
end

Test.print_test #=> red

Ваша ошибка в том, что переменная @color одинакова для:

module SharedVar
  @color
end

и

module SharedVar
  def show_color
    @color
  end
end

что не так.

В первом примере переменная экземпляра принадлежит объекту SharedVar, а во втором примере переменная экземпляра принадлежит объекту, в который вы включаете модуль.

Другое объяснение self указатель. В первом примере указатель self устанавливается на объект модуля SharedVar, поэтому ввод @color будет ссылаться на объект SharedVar, и нет связи с другим объектом. Во втором примере метод show_color может быть вызван только для некоторого объекта, т.е. ex1.show_color, поэтому указатель self будет указывать на объект ex1. Так что в этом случае переменная экземпляра будет ссылаться на ex1 объект.

0 голосов
/ 23 февраля 2012

Вы включили модуль в класс .. поэтому переменная экземпляра @color должна быть переменной экземпляра класса Example1 и Example2

Так что если вы хотите получить доступ к переменной @color, значит, вы предполагаете создать объект для класса, а затем вы можете получить к нему доступ

Для Ex

irb(main):028:0> ex1.change_color('black')
=> "black"
irb(main):029:0> ex1.show_color
black
irb(main):031:0> ex2.change_color('red')
=> "red"
irb(main):032:0> ex2.show_color
red
...