在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
本节书摘来自华章出版社《Effective Ruby:改善Ruby程序的48条建议》一书中的第2章,第2.8节,作者 [美]彼得 J.琼斯(Peter J. Jones),更多章节内容可以访问云栖社区“华章计算机”公众号查看 第13条:通过"<=>"操作符实现比较和比较模块在第12条中提到了四种测试对象相等性的方法。如果你对对象的排序和比较有兴趣,那么你就需要进一步定义其他的比较操作符了。与等价操作符不同的是,类并没有从其他比较操作符中继承默认实现。还好,Ruby提供了一种简便的方式来实现它,这一点我们会在稍后讨论。 我想再次强调,一般说来类不会自动继承比较操作符,但有一个例外。这一点我们会在之后讨论,现在你要做的就是为这个类定义一个比较操作符,也就是“<=>”操作符。这个特别的操作符其实继承自Object类,但是这个继承的实现却是不完整的。让我们看看如果试图对一组Version类的对象进行排序时会发生什么: 这对我们来说并没有什么帮助。要怪就怪“<=>”操作符的默认实现好了。它只考虑了两个对象是否相同(使用equal?和“===”操作符),却没有按我们的需要完整地进行比较。如果两个被比较的对象不相同就返回nil,从而告诉sort方法这个比较是非法的。但也还好,毕竟你不能对一个通用的实现抱有太大的期望,所以咱们还是自己动手实现一个吧。 当编写“<=>”时,通常的做法是将比较方法代理给对象的实例变量。Version类中的三个变量都是Fixnum类的实例,这意味着它们都实现了可用的“<=>”操作符。这大大简化了我们的工作。为了比较版本号,我们需要考虑接收者(左操作数)中的实例变量以及那些参数中的实例变量(右操作数)从主版本到修订版本的顺序。一旦接收者中有一个变量与参数中对应的变量不相符,我们就可以停止比较。换句话说,如果要比较的两个版本的主版本号不相符,那么无需比较次版本号或修订版本号就已经可以知道谁大谁小。但是如果主版本号相同,就需要比较次版本号。以此类推,当次版本号也相同时就需要比较修订版本号。当所有部分和另一个都相同时,我们的比较操作符应该返回0以表示两个Version对象的等价性。而其他情况下,只需使用“<=>”操作符对第一组不匹配的变量进行操作,并将其结果返回。思考Version类中比较操作符的实现: 每个部分都会分别被比较,并将其比较的结果存放于一个数组中。我们需要做的仅仅是在这个数组中寻找第一个非零元素(第一对不相同的部分)。如果所有部分都相同,那么detect方法就会返回nil,而此时比较操作符返回0。现在,我们就可以对一组Version对象进行排序了。 为了完整地实现Version对象的比较功能,我们还需添加一段代码。除了排序之外,我们想让这些对象能够使用诸如“>”、“>=”这样的操作符。事实上,这五个操作符构成了完整的排序操作符,它们是:“<”、“<=”、“==”、“>”和“>=”。你如果知道我们无需自己手动实现它们一定会很高兴吧。我们要做的只是引入一个名为Comparable的模块。 就这么简单。现在我们可以使用所有的比较操作符以及一个额外的helper方法: 当使用Comparable模块时,还有些因素需要考虑一下。首先,对于某些类你可能想实现自己的“==”操作符,因此这比使用Comparable模块中的方法间接一些。在第12条中有一个很好的例子,其在做比较之前对数值类型进行了转换。如果你想这样做,你需要编写自己的等价操作符或者改变使“<=>”操作符返回0的条件。具体如何选择,应由你希望其他的比较运算符表现出什么样的行为来决定。 要点回顾 |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论