2017-09-18 11 views
1

L'exemple de code et de sortie peuvent être trouvés ici:question l'accès variable d'instance via la méthode de module inclus

module A 
    def self.included(base) 
    base.include InMethods 
    end 

    module InMethods 
    def mem 
     @mem ||= [] 
    end 

    def add(n) 
     mem += n 
    end 
    end 
end 

class Help 
    include A 
end 

h = Help.new 
h.add(1) 
# in `add': undefined method `+' for nil:NilClass (NoMethodError) 

Fondamentalement, je suis inclus un module qui comprend un sous-module, mais le vrai problème est avec les méthodes et la variable d'instance. C'est un modèle commun pour moi, mais puisque j'essaie de le faire à partir d'un module que j'ai inclus, j'ai des problèmes.

Répondre

2

Ceci n'a en fait rien à voir avec modules/inclusion/héritage/peu importe. Vous obtenez la même erreur dans une classe régulière.

class Help 
    def mem 
    @mem ||= 0 
    end 

    def add(n) 
    mem += n 
    end 
end 

Help.new.add(1) 
# test.rb:16:in `add': undefined method `+' for nil:NilClass (NoMethodError) 

Lorsque vous utilisez le sucre syntaxique mem +=, Ruby développe en fait cela en mem = mem +. Le premier problème est que cela est interprété de gauche à droite, donc le mem = définit une variable locale mem qui masque votre méthode. Ainsi, la seconde mem référence une variable locale définie mais non définie et vous obtenez nil.

Le deuxième problème est que vous n'avez pas défini de méthode de setter mem=, donc il ne peut pas changer du tout @mem!

Pour résoudre les problèmes, vous pourriez faire

attr_writer :mem 

def add(n) 
    self.mem += n 
end 
+0

Il est vrai que mon libellé est erroné. Je voulais dire "désactivé" pour le second. Un artefact étrange de la façon dont Ruby définit les variables locales. – Max