在 ruby 中创建匿名 类

Creating anonymous classes in ruby

根据示例中的“well ground ruby​​ist”,c“包含”或“指向”一个匿名 class。我说得对吗,C 不是匿名的 class?这真的有点令人困惑。

    >> c = Class.new
    => #<Class:0x0000000006c4bd40>
    >> o1 = c.new
    => #<#<Class:0x0000000006c4bd40>:0x0000000006b81ec8>
    >> o1.class
    => #<Class:0x0000000006c4bd40>
    >>
    >> C = Class.new
    => C
    >> o2 = C.new
    => #<C:0x0000000006494480>
    >> o2.class
    => C
  • Class.new 创建一个新的匿名(未命名)class

  • c = Class.new 创建一个新的匿名 class 并将其分配给 局部变量 c

  • C = Class.new 创建一个新的匿名 class 并将其分配给 constant C

虽然这两个赋值看起来几乎相同,但有一个微妙但重要的区别:将匿名 class 赋值给 constant 设置 name class 到常量的名称:

c = Class.new
c.name #=> nil

C = Class.new
C.name #=> "C"

Class.new 的文档中也提到了这一点:

You can give a class a name by assigning the class object to a constant.

此时,class 不再是匿名的。它现在有了一个名称,我们可以使用常量 C.

形式的名称来引用它

“匿名”或“命名”class 的概念在 Ruby 中没有真正意义。 class 就像任何其他对象一样只是一个对象。我们也没有“匿名”或“命名”整数或字符串。 class 只是一个类似于整数或字符串的对象:它可以从方法中 return 编辑,可以分配给局部变量、实例变量、class 变量、全局变量变量或常量。

这不同于 Java 等具有主格类型系统的编程语言,在后者中,具有或不具有名称的类型会有很大的不同。

理解这一点非常重要:class 只是一个恰好是 Class class 实例的对象。没什么特别的。它只是一个像整数、字符串或数组这样的对象。

classes(实际上是模块)do 有一个名为 Module#name 的方法,但同样,该方法没有什么特别之处。您也可以将 #name 方法添加到您自己的 classes 中。

唯一的特殊之处在于,当class(实际上是一个模块)被赋值时(无论是使用赋值运算符=,还是反射性地使用 Module#const_set 方法)第一次 到一个常量,该常量的路径成为 Module#name 的 return 值:

a = Module.new
a.name #=> nil

b = a
b.name #=> nil

module A; module B; module C; end end end

A::B::C.const_set(:D, b)

a.name #=> 'A::B::C::D'

A::B::C::D = nil
A::B::C.send(:remove_const, :D)
A::B::C = nil
A::B.send(:remove_const, :C)
A::B = nil
A.send(:remove_const, :B)
A = nil
Object.send(:remove_const, :A)

a.name #=> 'A::B::C::D'

因此,如您所见,“匿名”和“命名”之间的区别几乎不存在,即使您可以构造一个有意义的定义,那么区分仍然无关紧要。