我最近在 Rails 代码库中进行了一些代码重构,在其中我转换了一些定义了一些类的代码,如下所示(类主体被省略):
foo/user_bar.rb
:
module Foo
class UserBar; end
end
foo/sub_user_bar.rb
:
module Foo
class SubUserBar < UserBar; end
end
...到:
在foo/bar/user.rb
:
module Foo
module Bar
class User; end
end
end
在foo/bar/sub_user.rb
:
module Foo
module Bar
class SubUser < User; end
end
end
这引入了一个微妙的问题,因为已经存在一个名为 User
的顶级类。 (Rails 模型)和 SubUser
是从那里派生的,而不是从User
在同一个模块中。我猜这是因为 Rails 加载类的顺序是不可预测的......?
无论如何,我发现我可以通过声明 SubUser
来消除歧义。像这样上课:
class SubUser < self::User
...这似乎有效,尽管我在适度的搜索中找不到任何示例。不过,它看起来确实有点奇怪。现在我担心我真的应该为我的模块中的每个类都这样做,以防万一引入同名的顶级类。
在我公司的代码库中有两种风格的模块内类声明:
class A::B::Foo; end
和:
module A; module B; class Foo; end; end; end
我一直更喜欢后一种方法,因为它允许访问模块中没有完全限定名称的其他名称,但现在我发现使用它时可能存在陷阱。那么这里的最佳做法是什么?
- 不要在
module
中声明类;始终使用完全限定名称 (class A::B::C::Foo < A::B::C::Bar
) - 在
module
中声明类但始终完全限定父类(super class)名称 (module A; module B; module C; class Foo < A::B::C::Bar
) - 在
module
中声明类并使用不合格的名称,但始终使用self::
在同一模块中扩展类时 - 在
module
中声明类并使用非限定名称,但要注意顶级 namespace 中可能发生的名称冲突(似乎有风险)
或者 Ruby 和/或 Rails 是否提供了其他更简洁的方法来解决问题?
最佳答案
通常在有歧义的地方指定完整的命名空间路径:
module Foo
module Bar
class SubUser < Foo::Bar::User; end
end
end
这可能看起来很冗长,但它也是具体和明确的。
在您想要引用文字顶级 User
的地方,您需要指定 ::User
。
关于ruby-on-rails - Ruby 类名称解析中的歧义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54260744/