Ruby 区别于;甲级;B类“;及;A类::B类“;

Ruby 区别于;甲级;B类“;及;A类::B类“;,ruby,Ruby,这两者之间的区别是什么: class A class B end end 及 更新:这两种方法并不完全相同 在第二种方法中,B无法访问A中定义的常量 此外,正如Matheus Moreira正确指出的那样,在第二种方法中,A必须先定义,然后才能定义A::B 还有什么区别呢?它们是一样的。它们是书写同一事物的不同方式。第一种是编写它的简单方法,但通常情况下,一旦类/模块变大,就很难跟踪嵌套。使用第二种方式,可以避免在外观上嵌套。两种不同的方式来表达相同的内容。这是因为类B是一个内部类或

这两者之间的区别是什么:

class A
  class B
  end
end


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

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

此外,正如Matheus Moreira正确指出的那样,在第二种方法中,
A
必须先定义,然后才能定义
A::B


还有什么区别呢?

它们是一样的。它们是书写同一事物的不同方式。第一种是编写它的简单方法,但通常情况下,一旦类/模块变大,就很难跟踪嵌套。使用第二种方式,可以避免在外观上嵌套。

两种不同的方式来表达相同的内容。这是因为类B是一个内部类或嵌套类,只能通过A接口访问

> class A
..  def say
....  "In A"
....end
..
..  class B
....  def say
......  "In B"
......end
....end
..end
=> nil

> A.new.say
=> "In A"
> B.new.say
=> #<NameError: uninitialized constant B>
> A::B.new.s­ay
=> "In B"
>A类
..  戴夫说
....  “在一个
……结束
..
..  B类
....  戴夫说
......  “在B中”
……结束
……结束
……结束
=>零
>新的
=>“在A中”
>新的
=> #
>A::B.新的。是的
=>“在B中”

> class A
..  def say
....  "In A"
....end
..end
=> nil

> class A::B
..  def say
....  "In B"
....end
..end
=> nil

> A.new.say
=> "In A"
> B.new.say
=> #<NameError: uninitialized constant B>
> A::B.new.s­ay
=> "In B"
>  
>A类
..  戴夫说
....  “在一个
……结束
……结束
=>零
>A类::B类
..  戴夫说
....  “在B中”
……结束
……结束
=>零
>新的
=>“在A中”
>新的
=> #
>A::B.新的。是的
=>“在B中”
>  

在Ruby中,模块和类分别是和类的实例。它们的名称是从分配给它们的常量派生出来的。当你写作时:

class A::B
  # ...
end
class A
  class B
    # ...
  end
end
你实际上是在写:

A::B ||= Class.new do
  # ...
end
这是有效的常量赋值语法,并假设
A
常量已正确初始化,并且它引用了
模块

例如,考虑如何定义类:

class A
  # ...
end
实际发生的情况是:

Object::A ||= Class.new do
  # ...
end
现在,当你写作时:

class A::B
  # ...
end
class A
  class B
    # ...
  end
end
实际发生的情况如下所示:

(Object::A ||= Class.new).class_eval do
  (A::B ||= Class.new).class_eval do
    # ...
  end
end
以下是正在发生的事情,顺序如下:

  • 一个新的
    实例被分配到
    对象
    常量,除非它已经初始化
  • 新的
    实例被分配到
    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
    
    据介绍,Ruby核心团队将“当前类”称为
    cref
    。不幸的是,作者没有详细说明,但正如他所指出的,它与
    self
    的上下文是分离的


    ,cref
    是一个链表,表示某个时间点的模块嵌套

    当前的
    cref
    用于常量和类变量查找和 对于
    def
    undef
    alias


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

    然而,有一个微妙的区别。在编写
    class A::B
    时,假设
    A
    类已经定义。如果没有,您将得到一个
    namererror
    ,而
    B
    将根本不被定义

    正确编写嵌套模块:

    class A
      class B
      end
    end
    

    在尝试定义
    B

    之前,确保
    A
    类存在。我已更新问题,以显示这两种方法不相同。我已更新问题,以显示这两种方法不相同。@nickh,您无需编辑问题以包含答案。你应该这样做。对常数是如何定义的很好的解释。谢谢当使用
    class A::B
    定义
    B
    时,您知道为什么
    B
    不能访问
    A
    中的常量吗?解释得很好。这是很多Ruby开发人员都不会花时间学习的重要内容。谢谢我已经更新了这个问题,以表明这两种方法是不同的。@nickh我认为这些差异是微不足道的,是预先假定的,所以我没有提到它们。指出它们与说“嗯,字符串
    class B
    看起来与
    class A::B
    不同”没有太大区别,但您没有提到这一点。