ruby-on-rails - Ruby 类名解析中的歧义
问题描述
我最近在 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
) - 在 a 中声明类,
module
但始终完全限定超类名称 (module A; module B; module C; class Foo < A::B::C::Bar
) - 在 a 中声明类
module
并使用非限定名称,但self::
在同一模块中扩展类时始终使用 - 在 a 中声明类
module
并使用非限定名称,但要注意顶级命名空间中可能的名称冲突(似乎有风险)
或者 Ruby 和/或 Rails 是否提供了其他更简洁的方法来解决问题?
解决方案
通常,如果您指定完整的命名空间路径有歧义:
module Foo
module Bar
class SubUser < Foo::Bar::User; end
end
end
这可能看起来很冗长,但它也是具体且明确的。
User
你想在哪里引用你指定的文字顶层::User
。
推荐阅读
- android - 在列表视图中单击组标题时出错
- json - 如何在 golang 中轻松编辑 JSON 类型(如 Node.js)
- python - 这个for循环如何在python中使用
- laravel - laravel 控制台中的错误请求状态消息
- javascript - 处理大量数据的最佳方法
- r - 避免嵌套列表的嵌套 for 循环
- javascript - 接口类型的数组
- c# - 使用 HtmlAgilityPack 进行 Web 查询抛出 System.Net.WebException:请求被中止:无法创建 SSL/TLS 安全通道
- typescript - 如何从格式为“08/01/2018”的日期减少 1 年?
- java - 更新 Spinner 失去了它的风格