2011-03-22 3 views
2

Je suis un démarreur Ruby. J'ai trouvé les deux sont assez similaires (en sortie), mais je ne pouvais pas comprendre la différence dans le contexte ci-dessous. Par exemple, j'ai une classeQuelle est la différence entre class_eval et class << className?

class Say 
    def self.hello 
    puts "hello" 
    end 
end 

et peut être étendu comme celui-ci

class << Say 
    def hi 
    puts "hi" 
    end 
end 

et aussi comme celui-ci

Say.class_eval do 
    def self.bye 
    puts "bye" 
    end 
end 

Quand dois-je utiliser << et quand class_eval?

Répondre

13

class_eval n'a vraiment rien à voir avec class << className.

A.class_eval do 
    ... 
end 

est équivalent à

class A 
    ... 
end 

avec quelques différences. class_eval utilise un bloc (ou une chaîne, mais en l'ignorant pour l'instant) ce qui signifie qu'il se ferme sur la portée lexicale qui le contient. En d'autres termes, vous pouvez utiliser des variables locales de la portée environnante. Le bloc de classe commune introduit une toute nouvelle portée. De même, vous pouvez créer le bloc et le passer à de nombreux class_eval différents, et le corps du bloc sera exécuté dans le contexte de la classe que vous appelez class_eval.

class << className ouvre la classe singleton de className, vous permettant de définir des méthodes de classe.

class << A 
    def foo 
    ... 
    end 
end 

est le même que

def A.foo 
    ... 
end 

Notez que ce sont des méthodes de classe Oly si A se trouve être une classe (presque) tous les objets Ruby ont des classes singleton et vous pouvez définir des méthodes pour les utiliser l'une de ces deux syntaxes. L'avantage de class << obj est principalement si vous définissez de nombreuses méthodes singleton en une seule fois.

1

Comme déjà dit class_eval a vraiment pas grand-chose à voir avec

class <<self 

même si elles semblent faire la même chose dans votre exemple (alors que l'effet est similaire, il ne fait pas la même chose, il y a des subtiles différences).

Voici un autre exemple où l'utilisation de la seconde forme est beaucoup plus claire:

class A 

end 


a = A.new 
b = A.new 

class <<b 
    def say_hi 
    puts "Hi !" 
    end 
end 


b.say_hi # will print "Hi !" 
a.say_hi # will raise an undefined method 

a et b sont les deux objets de la même classe A, mais nous avons ajouté une méthode à la méta-classe de b de sorte que le La méthode say_hi n'est disponible que pour l'objet b.

Questions connexes