2010-05-29 2 views
1

cette classe Tenir compte de l'exploitation forestière très simple:Pourquoi la méthode de cette simple classe de test n'est-elle pas héritée dans Ruby?

class MockLog 
    # ... 
end 

Ajoutons l'exploitation forestière à toutes nos classes:

class Module 
    def has_logging() 
    class_eval { 
     @log = MockLog.new 
     def log 
     self.class.instance_variable_get :@log 
     end 
    } 
    end 
end 

Maintenant, pourquoi ça ne marche pas?

class Foo 
    has_logging 
end 
Foo.new.log.nil? # => false, as expected 

class Bar < Foo 
end 
Bar.new.log.nil? # => true?! Why wasn't the `log` method inherited? 

Répondre

1

La méthode du journal a été hérité (si ce n'était pas, vous obtiendrez un NoMethodError), mais votre variable de niveau de classe d'instance n'a pas été, donc instance_variable_get retourné nul. Vous devez déclarer une variable de classe régulière comme:

class Module 
    def has_logging() 
    class_eval { 
     @@log = MockLog.new 
     def log 
     @@log 
     end 
    } 
    end 
end 

class Foo 
    has_logging 
end 

class Bar < Foo 
end 

Maintenant, il sera hérité. Voir Class and Instance Variables In Ruby

+0

Hmm .. mais si la méthode 'log' a été héritée, alors pourquoi retourne-t-elle vrai lorsque nous demandons si elle est nulle? –

+0

Je ne pense pas que ce soit une bonne idée. Maintenant si vous voulez avoir un _different_log dans 'Bar', il ne peut pas remplacer le' @@ log' dans 'Foo'; ils partageront la même instance de '@@ log'. Je pense que le comportement qu'il souhaite est "les sous-classes de' Foo' utiliseront '@@ log' sauf si elles sont surchargées, mais si elles appellent elles-mêmes' has_logging', alors cette sous-classe aura son propre '@@ log'". –

+0

Autrement dit, disons que vous avez 'class Quux

Questions connexes