有什么区别:
class A class B end end
和
class A end class A::B end
更新:这两种方法并不完全相同.
在第二种方法中,B无法访问A中定义的常量.
此外,正如Matheus Moreira所说,在第二种方法中,必须在定义A :: B之前定义A.
还有什么其他差异?
解决方法
在Ruby中,模块和类分别是
Module
和
Class
类的实例.它们从它们被赋予的常量中得出它们的名称.当你写:
class A::B # ... end
你是在写作:
A::B ||= Class.new do # ... end
哪个是有效的常量赋值语法,并假设A常量已正确初始化,并且它指的是模块或类.
例如,考虑如何定义类:
class A # ... end
实际发生的是:
Object::A ||= Class.new do # ... end
现在,当你写:
class A class B # ... end end
实际发生的事情如下:
(Object::A ||= Class.new).class_eval do (A::B ||= Class.new).class_eval do # ... end end
这是正在发生的事情,按顺序:
>除非已初始化,否则新的Class实例将被赋予Object的A常量.
>新的Class实例被赋予A的B常量,除非它已经初始化.
这样可以在尝试定义任何内部类之前确保所有外部类的存在.
范围也有变化,允许您直接访问A的常量.相比:
class A MESSAGE = "I'm here!" end # Scope of Object class A::B # Scope of B puts MESSAGE # NameError: uninitialized constant A::B::MESSAGE end # Scope of Object class A # Scope of A class B # Scope of B puts MESSAGE # I'm here! end end
根据this blog post,Ruby核心团队将“当前类”称为cref.不幸的是,作者没有详细说明,但正如他所指出的那样,它与自我的背景是分开的.
As explained here,cref是一个链表,表示模块在某个时间点的嵌套.
The current
cref
is used for constant and class variable lookup and
fordef
,undef
andalias
.
正如其他人所说,他们是表达同一事物的不同方式.
然而,有一个微妙的区别.当你编写A :: B类时,你假设已经定义了A类.如果没有,您将获得NameError,并且根本不会定义B.
编写正确嵌套的模块:
class A class B end end
在尝试定义B之前确保A类存在.