web-dev-qa-db-fra.com

Variables d'instance dans les modules?

Comment est-il possible que je puisse avoir des variables d'instance dans un module même si je ne peux pas créer une instance du module? Quel serait le but de @stack dans le module Stacklike ci-dessous?

module Stacklike
  def stack
    @stack ||= []
  end
end
34
Hommer Smith

Considérez la variable d'instance comme quelque chose qui existera dans n'importe quelle classe qui inclut votre module, et les choses ont un peu plus de sens:

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

affichera "1"

43
mcfinnigan

Voir ci-dessous:

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

Sortie:

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

Explication: Oui, les variables d'instance Module sont présentes dans le class lorsque vous les include dans la classe. Mais vous pouvez voir que p a.instance_variable_defined?(:@stack) affiche false car @stack N'est toujours pas défini tant que A . Au point B J'ai défini la variable d'instance @stack. Ainsi, l'instruction au point C , sort comme true. Signifie que les variables d'instance de module ne sont pas créées par le module lui-même, mais cela peut être fait par les instances de class si class incluait ce module. L'instruction dans E affiche [] Comme toujours ce point, la variable d'instance n'a pas été définie, mais si vous voyez la sortie pour la ligne D , il est prouvé que @stack est à l'intérieur de l'objet a de class A.

Pourquoi une telle conception?

Il s'agit de la conception ou parfois des exigences. Supposons que l'on vous ait demandé d'écrire un code d'opération de pile qui sera utilisé par deux sociétés de réservation de billets, dites A et B. Maintenant, A ont une politique de pile pour leurs clients, mais ils ont également plus de formalités à ce sujet. La société B utilise également une politique de pile avec ses propres formalités, différente de A. Ainsi, en cas de conception d'une opération Stack à l'intérieur de class A Et class B, Meilleure idée de l'écrire dans un endroit commun, comme A et B ont cette fonctionnalité en commun. À l'avenir, si une autre société C vient à vous, vous pouvez également utiliser ce module dans sa classe, sans réécrire la même fonctionnalité pour chaque A, B et C. Il peut y avoir plus de réflexions mais j'espère que cela vous aidera à répondre vous-même pour votre dernière partie des questions.

C'est tout sur le concept. J'espère que cela aide.

À votre santé!!

13
Arup Rakshit

Lorsque vous incluez un module dans une classe, toutes ses méthodes d'instance sont effectivement "collées" dans la classe Host. Donc si vous avez:

class Lifo
  include Stacklike
end

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

l a maintenant une variable d'instance @stack, importé de Stacklike.

5
Chowlett

Lorsque vous incluez le module Stacklike dans une autre classe, cette variable d'instance sera disponible comme si elle avait été définie dans cette classe. Cela vous donne la possibilité de définir et de gérer les variables d'instance de la classe de base à partir du module lui-même.

4
Erez Rabih