在 ruby 中创建匿名类
Posted
技术标签:
【中文标题】在 ruby 中创建匿名类【英文标题】:Creating anonymous classes in ruby 【发布时间】:2021-11-18 10:45:53 【问题描述】:根据示例中的“well ground rubyist”,c“包含”或“指向”一个匿名类。我是对的,C 不是匿名类吗?这真的有点令人困惑。
>> 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
【问题讨论】:
【参考方案1】:Class.new
创建一个新的匿名(未命名)类
c = Class.new
创建一个新的匿名类并将其分配给 局部变量 c
C = Class.new
创建一个新的匿名类并将其分配给 constant C
虽然两个赋值看起来几乎相同,但有一个微妙但重要的区别:将匿名类分配给 constant 将该类的 name
设置为常量的名称:
c = Class.new
c.name #=> nil
C = Class.new
C.name #=> "C"
Class.new
的文档中也提到了这一点:
您可以通过将类对象分配给常量来为类命名。
此时,该类不再是匿名的。它现在有了一个名称,我们可以使用该名称以常量C
的形式引用它。
【讨论】:
谢谢,就是这样! 可能值得注意的是,Module#const_set 可用于将匿名类c = Class.new
分配给常量:Object.const_set('C', c); C == c #=> true; C.name #=> "C"
。
@Cary:即使这样也有效:>> c = Class.new; => #<Class:0x000000000681d9d0> >> C = c; => C >> c.name; => "C"
【参考方案2】:
“匿名”或“命名”类的概念在 Ruby 中没有真正意义。类只是一个对象,就像任何其他对象一样。我们也没有“匿名”或“命名”整数或字符串。类只是一个像整数或字符串一样的对象:它可以从方法返回,可以分配给局部变量、实例变量、类变量、全局变量或常量。
这与 Java 等具有主格类型系统的编程语言不同,后者有或没有名称的类型会产生很大的不同。
理解这一点非常重要:一个类只是一个对象,它恰好是Class
类的一个实例。没什么特别的。它只是一个像整数、字符串或数组这样的对象。
什么类(实际上是模块)做,是一个名为Module#name
的方法,但同样,该方法并没有什么特别之处。您也可以将#name
方法添加到您自己的类中。
唯一的特别之处在于,当一个类(实际上是一个模块)被赋值时(无论是使用赋值运算符=
,还是反射性地使用Module#const_set
方法),第一次到一个常量,那个常量的路径变成了Module#name
的返回值:
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'
因此,如您所见,“匿名”和“命名”之间的区别实际上是不存在的,即使您可以构造一个有意义的定义,那么区别仍然无关紧要。
【讨论】:
以上是关于在 ruby 中创建匿名类的主要内容,如果未能解决你的问题,请参考以下文章