Étonnamment, les 10 réponses ici disent la même chose. Le '::' est un opérateur de résolution d'espace de noms, et oui c'est vrai. Mais il y a un problème que vous devez réaliser à propos de l'opérateur de résolution d'espace de noms en ce qui concerne l' algorithme de recherche constante . Comme Matz le décrit dans son livre, «Le langage de programmation Ruby», la recherche constante comporte plusieurs étapes. Premièrement, il recherche une constante dans la portée lexicale où la constante est référencée. S'il ne trouve pas la constante dans la portée lexicale, il recherche alors la hiérarchie d'héritage . En raison de cet algorithme de recherche constante, nous obtenons ci-dessous les résultats attendus:
module A
module B
PI = 3.14
module C
class E
PI = 3.15
end
class F < E
def get_pi
puts PI
end
end
end
end
end
f = A::B::C::F.new
f.get_pi
> 3.14
Alors que F hérite de E, le module B est dans la portée lexicale de F. Par conséquent, les instances F se référeront à la constante PI définie dans le module B. Maintenant, si le module B n'a pas défini PI, alors les instances F se référeront au PI constante définie dans la superclasse E.
Mais que se passerait-il si nous utilisions '::' plutôt que d'imbriquer des modules? Aurions-nous le même résultat? Non!
En utilisant l'opérateur de résolution d'espace de noms lors de la définition des modules imbriqués, les modules et classes imbriqués ne sont plus dans la portée lexicale de leurs modules externes. Comme vous pouvez le voir ci-dessous, PI défini dans A :: B n'est pas dans la portée lexicale de A :: B :: C :: D et donc nous obtenons une constante non initialisée lorsque nous essayons de faire référence à PI dans la méthode d'instance get_pi:
module A
end
module A::B
PI = 3.14
end
module A::B::C
class D
def get_pi
puts PI
end
end
end
d = A::B::C::D.new
d.get_pi
NameError: uninitialized constant A::B::C::D::PI
Did you mean? A::B::PI