我有一个单行代码,但它引起了我很多问题。
代码:
Time.at(100).send(:>=, Time.at(200))
主要问题是::>=
运算符的实现在哪里?
从源代码中我可以看到,time.c
中没有:>=
运算符的实现。是真的吗?如何知道哪个方法从那里实现:>=
?在文档中只描述了一种比较方法:<=>,但是对于如何将来自:<=>
的调用转换为:>=
,绝对不清楚。请描述:>=
是如何在c级被调用的调用跟踪。
>=
方法在Comparable
模块中定义。引用自文档:
Comparable mixin用于对象可以排序的类。该类必须定义
<=>
操作符,它将接收对象与另一个对象进行比较,根据接收对象是小于、等于还是大于另一个对象,返回一个小于0的值、返回0的值或返回一个大于0的值。如果另一个对象不具有可比性,则<=>
操作符应该返回nil。Comparable使用<=>
来实现传统的比较操作符(<
、<=
、==
、>=
和>
),以及between的方法。
Time
类包含Comparable
模块。
在Ruby中,x.y(...)
相当于x.send(y, ...)
,但像x + y
这样的东西最终也会转换为x.send(:+, y)
。大多数操作最终都是对某种对象的方法调用。
>=
操作符是一个语法元素,但它是通过调用左侧元素的>=
方法来实现的。就是这个代码:
Time.at(100).send(:>=, Time.at(200))
其中:>=
是表示>=
的符号,尽管您也可以使用'>='
代替,即使由于字符串开销而效率较低。
在任何情况下都相当于直接使用操作符:
Time.at(100) >= Time.at(200)
也就是说根本没有:>=
运算符。它是>=
运算符,由:>=
符号表示。
很多Ruby的内部在主流的"mri";由于性能的原因,Ruby版本都是用C语言实现的。这意味着您不能很容易地发现方法的实现位置:
Time.method(:>=).source_location
# => nil
这是因为没有涉及Ruby代码,它是一个"内部"代码。
值得注意的是,你不必直接实现像>=
这样的方法,有一些快捷方式可以自动派生这些方法,特别是在定义了<=>
方法的情况下,Comparable为你完成了这一点:
Comparable使用
<=>
实现传统的比较运算符(<
、<=
、==
、>=
和>
)和方法between?
。
换句话说,如果你在你的类中实现<=>
和include Comparable
,你可以免费获得这些。时间包括可比性吗?这很容易发现:
Time.ancestors
# => [Time, Comparable, Object, Kernel, BasicObject]
。
所以寻找一个特定的>=
方法是徒劳的,它是自动生成的。
定义Ruby C扩展的方式是通过编写C代码,然后通过使用如下的绑定桥接方法:
rb_define_method(rb_cTime, "<=>", time_cmp, 1);
将time_cmp()
函数与rb_cTime
类表示相关联。您也可以在文件中找到该函数的源代码。