Pourquoi Ruby ne trouve-t-il pas de classes dans une portée plus élevée lorsque le module est spécifié avec ::?


5

Je suis juste resté bloqué dessus pendant un moment. Prenez cette base:

module Top 
    class Test 
    end 

    module Foo 
    end 
end 

Plus tard, je peux définir des classes à l'intérieur Foo qui va Test en faisant ceci:

module Top 
    module Foo 
    class SomeTest < Test 
    end 
    end 
end 

Cependant, si je tente de minimiser indentation en utilisant :: pour indiquer le module:

module Top::Foo 
    class Failure < Test 
    end 
end 

Cela échoue avec:

NameError: uninitialized constant Top::Foo::Test

Est-ce un bug, ou est-ce simplement une conséquence logique de la façon dont Ruby résout les noms de variables?

7

Is this a bug, or is it just a logical consequence

C'est une "bizarrerie". Certains considèrent comme un bug.

Les étendues parentes utilisées pour rechercher les constantes non résolues sont déterminées par l'imbrication des modules. Il se trouve que lorsque vous utilisez module Top::Foo, cela crée un niveau d'imbrication au lieu de deux. OBSERVER:

module Top 
    module Foo 
    class SomeTest 
     Module.nesting # => [Top::Foo::SomeTest, Top::Foo, Top] 
    end 
    end 
end 

module Top::Foo 
    class SomeTest 
    Module.nesting # => [Top::Foo::SomeTest, Top::Foo] 
    end 
end 
+2

Sons comme un bug pour moi: P Mais la réponse très instructif, merci 17 déc.. 152015-12-17 15:46:16

  0

je dirais que je considère un bug, a trouvé un rapport qui que ce soit d'un bug dans le rubis à ce sujet? Je voudrais contribuer à la discussion et regarder ce qui serait impliqué dans la réparation de cela. 27 janv.. 172017-01-27 11:39:17

  0

Note: trouvé un lien indiquant que c'est intentionnel [ici] (https://bugs.ruby-lang.org/issues/11705) 27 janv.. 172017-01-27 11:44:30

+1

[This] (https://bugs.ruby-lang.org/issues/6810) semble être le rapport de bug pour ce comportement. Espérons que Matz décide de le ramasser. :) 27 janv.. 172017-01-27 11:59:42


1

Ceci est prévu. L'utilisation de :: modifie la portée de la recherche constante et s'attend à ce que Test soit défini sous Top::Foo.

Pour obtenir le résultat attendu, vous pouvez écrire:

module Top::Foo 
    class SomeTest < Top::Test 
    end 
end 

ou:

module Top 
    class Foo::SomeTest < Test 
    end 
end 

ou même:

class Top::Foo::SomeTest < Top::Test 
end