是什么使我无法在Ruby中包含类? [英] What prevents me from including a class in Ruby?
问题描述
我正在尝试了解一些Ruby内部知识:
I'm trying to understand some Ruby internals:
尝试 include
而不是 module ,会导致 TypeError
:(这是设计使然)
Attempting to include
a class instead of a module, results in a TypeError
: (that's by design)
class C
end
class Foo
end
Foo.include(C)
#=> TypeError: wrong argument type Class (expected Module)
我想知道该类型检查的工作原理
I would like to know how that type check works "under the hood".
由于类是模块,我假设Ruby会检查参数是否为的实际实例模块
:
Since classes are modules, I assumed Ruby checks whether the argument is an actual instance of Module
:
C.is_a?(Module) #=> true
C.instance_of?(Module) #=> false
听起来合理,不是吗?
但是当我定义自己的 Module
子类并创建该子类的实例时,它就可以正常工作:
But when I define my own Module
subclass and create an instance of that subclass, it works just fine:
class Klass < Module
end
K = Klass.new
Foo.include(K)
# no error
但是 K
是 Klass $ c $的一个实例c>,就像
C
是 Class
的实例一样。并且 Klass
是 Module
的子类,就像 Class
:
But K
is an instance of Klass
, just like C
is an instance of Class
. And Klass
is a subclass of Module
, just like Class
:
K.is_a?(Module) #=> true
K.instance_of?(Module) #=> false
K.class #=> Klass
C.class #=> Class
Klass.superclass #=> Module
Class.superclass #=> Module
那么该类型检查了 include
实际上是吗?
So what does that type check in include
actually do?
是否存在一个允许Ruby告诉类中模块的隐藏属性?
Is there a hidden property that allows Ruby to tell modules from classes?
是特定于实现的:我对YARV / MRI特别感兴趣。
Since this is implementation specific: I'm especially interested in YARV/MRI.
推荐答案
正如@Stefan所说, Module#include
调用宏 Check_Type(module,T_MODULE)
。您可以在 https://ruby-doc.org中找到它/core-2.6/Module.html#method-i-include
As @Stefan commented, Module#include
calls the macro Check_Type(module, T_MODULE)
. You can find this in https://ruby-doc.org/core-2.6/Module.html#method-i-include
进一步挖掘源代码,您可以在头文件中找到该代码ruby.h ,有一行
Further digging the source code, you can find that in the header file ruby.h, there's a line
#define Check_Type(v,t) rb_check_type((VALUE)(v),(t))
所以 Check_Type
只是 rb_check_type
的方便别名,您可以在 error.c <中找到 rb_check_type
的定义。 / strong>:
so Check_Type
is just a handy alias of rb_check_type
, and you can find the definition of rb_check_type
in error.c:
void
rb_check_type(VALUE x, int t)
{
int xt;
if (x == Qundef) {
rb_bug(UNDEF_LEAKED);
}
xt = TYPE(x);
if (xt != t || (xt == T_DATA && RTYPEDDATA_P(x))) {
unexpected_type(x, xt, t);
}
}
int t
是类型的唯一 ID,而 int xt
是 x $ c的实际类型的ID $ c>。您会看到
if(xt!= t || ...)
,因此 Check_Type
正在检查类型对等,
The int t
is the unique "ID" for a type, and int xt
is the ID of the actual type of x
. You can see if (xt != t || ...)
, so Check_Type
is checking the type equivalence, not the is-a relation.
Ruby检查所包含的模块是否实际上是一个模块而不是课程。
Ruby checks if the included module is actually a module and not a class.
这篇关于是什么使我无法在Ruby中包含类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!