是什么使我无法在Ruby中包含类? [英] What prevents me from including a class in Ruby?

查看:65
本文介绍了是什么使我无法在Ruby中包含类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试了解一些Ruby内部知识:

I'm trying to understand some Ruby internals:

尝试 class 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 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 。您会看到 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆