ruby – “A级之间的差异; B级“和”A类:: B“

前端之家收集整理的这篇文章主要介绍了ruby – “A级之间的差异; B级“和”A类:: B“前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
有什么区别:
class A
  class B
  end
end

class A
end

class A::B
end

更新:这两种方法并不完全相同.

在第二种方法中,B无法访问A中定义的常量.

此外,正如Matheus Moreira所说,在第二种方法中,必须在定义A :: B之前定义A.

还有什么其他差异?

解决方法

在Ruby中,模块和类分别是 ModuleClass类的实例.它们从它们被赋予的常量中得出它们的名称.当你写:
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
for def,undef and alias.

正如其他人所说,他们是表达同一事物的不同方式.

然而,有一个微妙的区别.当你编写A :: B类时,你假设已经定义了A类.如果没有,您将获得NameError,并且根本不会定义B.

编写正确嵌套的模块:

class A
  class B
  end
end

在尝试定义B之前确保A类存在.

猜你在找的Ruby相关文章