Quel est la différence entre class_eval et de la classe << className?
-
28-10-2019 - |
Question
Je suis un Rubis starter.J'ai trouvé ces 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 classe
class Say
def self.hello
puts "hello"
end
end
et peut être étendu comme ceci
class << Say
def hi
puts "hi"
end
end
et aussi comme ça
Say.class_eval do
def self.bye
puts "bye"
end
end
Quand dois-je utiliser <<
et quand class_eval
?
La solution
class_eval
n'a pas vraiment rien avoir à faire 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 de caractères, mais en ignorant que pour le moment), ce qui signifie qu'il se ferme sur le contenant de la portée lexicale.En d'autres termes, vous pouvez utiliser des variables locales à partir de l'environnement de la portée.La commune de la classe bloc introduit un tout nouveau champ d'application.De même, vous pouvez créer le bloc et de le transmettre à beaucoup de différents class_eval, et le corps du bloc sera exécuté dans le contexte de la classe que vous appelez class_eval sur.
class << className
ouvre la classe singleton de className
, vous permettant de définir les méthodes de la classe.
class << A
def foo
...
end
end
Est le même que
def A.foo
...
end
Notez qu'ils sont oly les méthodes de la classe si l'Un se trouve être une classe de (presque) tous les objets en ruby ont singleton classes et vous pouvez définir des méthodes à l'aide de l'une de ces deux syntaxes.L'avantage de class << obj
est principalement si vous êtes à la définition de nombreux singleton méthodes en une seule fois.
Autres conseils
Comme déjà dit, class_eval n'a vraiment pas grand chose à voir avec
class <<self
même s'ils semblent faire la même chose dans votre exemple (bien que l'effet soit similaire, il ne fait pas la même chose, il y a des différences subtiles).
Voici un autre exemple où l'utilisation du deuxième formulaire 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 tous deux des objets de la même classe A mais nous avons ajouté une méthode à la métaclasse de b donc la méthode say_hi n'est disponible que pour l'objet b.