【发布时间】:2020-05-03 02:31:03
【问题描述】:
我正在尝试了解一些 Ruby 内部结构:
尝试使用include 一个类 而不是一个模块,会导致TypeError:(这是设计使然)
class C
end
class Foo
end
Foo.include(C)
#=> TypeError: wrong argument type Class (expected Module)
我想知道这种类型检查是如何“在后台”工作的。
由于类是模块,我假设Ruby会检查参数是否是Module的实际实例:
C.is_a?(Module) #=> true
C.instance_of?(Module) #=> false
听起来很合理,不是吗?
但是当我定义自己的 Module 子类并创建该子类的实例时,它就可以正常工作了:
class Klass < Module
end
K = Klass.new
Foo.include(K)
# no error
但是K 是Klass 的一个实例,就像C 是Class 的一个实例一样。而Klass 是Module 的子类,就像Class:
K.is_a?(Module) #=> true
K.instance_of?(Module) #=> false
K.class #=> Klass
C.class #=> Class
Klass.superclass #=> Module
Class.superclass #=> Module
那么include 中的那种类型检查实际上做了什么?
是否有一个隐藏属性允许 Ruby 将模块与类区别开来?
由于这是特定于实现的:我对 YARV/MRI 特别感兴趣。
【问题讨论】:
-
也许它直接检查这是否是
Class的实例?K.is_a?(Class) #=> false,C.is_a?(Class) #=> true. -
@MarekLipka 在 C 源代码中我看到
Check_Type(module, T_MODULE),即明确检查 T_MODULE 但没有像“not T_CLASS”这样的逆向