Подтвердить что ты не робот

Переменные экземпляра в модулях?

Как возможно, что у меня могут быть переменные экземпляра в модуле, хотя я не могу создать экземпляр модуля? Какова была бы цель @stack в модуле Stacklike ниже?

module Stacklike
  def stack
    @stack ||= []
  end
end
4b9b3361

Ответ 1

Подумайте о переменной экземпляра как о том, что будет существовать в любом классе, который включает ваш модуль, и все будет иметь смысл:

module Stacklike
  def stack
    @stack ||= []
  end

  def add_to_stack(obj)
    stack.push(obj)
  end

  def take_from_stack
    stack.pop
  end
end

class ClownStack
  include Stacklike

  def size
    @stack.length
  end
end

cs = ClownStack.new
cs.add_to_stack(1)
puts cs.size

выведет "1"

Ответ 2

См. ниже:

p RUBY_VERSION
module Stacklike
  def stack
    @stack ||= []
  end

  def add_to_stack(obj)
    stack.push(obj)
  end

  def take_from_stack
    stack.pop
  end
end

class A
include Stacklike
end

a = A.new
p a.instance_variables #<~~ E
p a.instance_variable_defined?(:@stack) #<~~ A
a.add_to_stack(10) #<~~ B
p a.instance_variable_defined?(:@stack) #<~~ C
p a.instance_variables #<~~ D

Вывод:

"1.9.3"
[]
false
true
[:@stack]

Объяснение: Да, переменные экземпляра Module присутствуют в class, если вы include их внутри класса. Но вы можете видеть, что p a.instance_variable_defined?(:@stack) показывает false, поскольку @stack до сих пор не определен до A. В точке B я определил переменную экземпляра @stack. Таким образом, оператор в точке C выводит как true. Средние переменные экземпляра модуля не создаются самим модулем, но это может быть сделано экземплярами class, если в class включен этот модуль. Заявление в E выводит [], поскольку в этой точке переменная экземпляра не была определена, но если вы видите вывод для строки D, то доказано @stack находится внутри объекта a of class A.

Почему такой дизайн?

Это дизайн или иногда исходит из требований. Скажите, что вас попросили написать код операции стека, который будет использоваться двумя компаниями, осуществляющими бронирование билетов, Say a и B. Теперь a - политика стека для своих клиентов, чтобы обслуживать, но также они имеют больше формальности с этим. B компания также использует политику стека со своими формальностями, которая отличается от a. Таким образом, в случае проектирования Stack внутри class A и class B лучше написать его в общем месте, так как обе a и B имеют общую функциональность внутри них. В будущем, если к вам придет другая компания C, вы также можете использовать этот модуль в своем классе, не переписывая одну и ту же функциональность для каждого a, B и C. Могут быть больше мыслей, но надеюсь, что это поможет вам ответить на вопрос о своей последней части вопросов.

Что все о концепции. Надеюсь, что это поможет.

Ура!!

Ответ 3

Когда вы включаете модуль в класс, все его методы экземпляра эффективно "вставлены" в класс хоста. Поэтому, если у вас есть:

class Lifo
  include Stacklike
end

l = Lifo.new
l.add_to_stack(:widget)

Затем l теперь имеет переменную экземпляра @stack, введенную из Stacklike.

Ответ 4

Когда вы включаете модуль Stacklike в какой-то другой класс, эта переменная экземпляра будет доступна, как если бы она была определена в этом классе. Это дает вам возможность устанавливать и обрабатывать переменные экземпляра базового класса из самого модуля.