在 ruby 中创建匿名 类
Creating anonymous classes in ruby
根据示例中的“well ground rubyist”,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'
因此,如您所见,“匿名”和“命名”之间的区别几乎不存在,即使您可以构造一个有意义的定义,那么区分仍然无关紧要。
根据示例中的“well ground rubyist”,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
创建一个新的匿名(未命名)classc = Class.new
创建一个新的匿名 class 并将其分配给 局部变量c
C = Class.new
创建一个新的匿名 class 并将其分配给 constantC
虽然这两个赋值看起来几乎相同,但有一个微妙但重要的区别:将匿名 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'
因此,如您所见,“匿名”和“命名”之间的区别几乎不存在,即使您可以构造一个有意义的定义,那么区分仍然无关紧要。