Ruby中相等性判断的4种方法

很早就知道 ruby 有 4 种相等性判断方法,分别是:“==”,“===”,“equal?” 和 “eql?”,平常程序中都有使用,但是感觉对其缺乏深入理解,今天读 rails 部分源码的时候拿捏不定其中一个判断的意思,于是趁机深入研究了一番,总算觉得比较清楚了,今天做一下笔记,以作备忘。

“==” 最常见的相等性判断

“==” 使用最频繁,它通常用于对象的值相等性(语义相等)判断,在 Object 的方法定义中,“==” 比较两个对象的 object_id 是否一致,通常子类都会重写覆盖这个方法,通过比较内部值来判断对象是否相等。

比如 ActiveRecord::Base 对 “==” 的定义

代码如下:

def ==(comparison_object)
    super ||
      comparison_object.instance_of?(self.class) &&
      id.present? &&
      comparison_object.id == id
  end

通过 model 的 id 属性比较两个 ActiveRecord::Base 实例是否相等。

“===” 用于 case 语句的相容判断

“===” 主要用于 case 语句中对象的相容比较,看代码比较容易理解。

代码如下:

def what_is(obj)
  case obj
    when /abc/
      puts "include abc"
    when 3..5
      puts "in 3..5"
    when Symbol
      puts "It is a symbol"
    else
      puts "unkonwn"
  end
end

what_is("abcde") # =>  "include abc"
what_is(4)       # =>  "in 3..5"
what_is(:a)      # =>  "It is a symbol"
what_is(100)     # =>  "unknown"

case 背后是拿每一个 when 后面的对象与 obj 进行 === 方法计算比较,比如上面的代码就是 分别求 /abc/.===(obj) , (3..5).===(obj) , Symbol.===(obj) 。

关键得看 === 方法里如何定义, Class 类中, === 定义为 obj.is_a?(klass),所以 case 可以现实 obj 的类型判断。

特别要注意的是和其他相等判断不同 “===” 通常没法交换,也就是很可能 a.===(b) != b.===(a) ,比如 /abc/ === "abcd" 为 true,但 "abcd" === /abc/ 为 false。

“equal?” 相同对象判断

“equal?” 其实是最简单的,但是也是最容易让人搞混的判断。说它简单是因为这个方法的语义是比较两个对象是否相同(是否有相同的 object_id),Object 的方法适用所有对象,不应该对其重写覆盖。说它容易让人搞混,是因为 ruby 和 java 中 “==” 和 “equal?” 方法的语义正好是相反的,ruby 中 “equal?” 表示对象引用相同,而 java 表示对象值相同。

“eql?” 对象 hash 值判断

eql? 用于对象 hash 值判断,如果两个对象的 hash 值相等,就返回 true,否则返回 false。Object 的定义里,“eql?” 和 “==” 是等价的。通常可以把 “eql?” 看作比 “==” 更严格的相等,比如:

代码如下:

1 == 1.0     #=> true
1.eql? 1.0   #=> false

(0)

相关推荐

  • Ruby中相等性判断的4种方法

    很早就知道 ruby 有 4 种相等性判断方法,分别是:"==","===","equal?" 和 "eql?",平常程序中都有使用,但是感觉对其缺乏深入理解,今天读 rails 部分源码的时候拿捏不定其中一个判断的意思,于是趁机深入研究了一番,总算觉得比较清楚了,今天做一下笔记,以作备忘. "==" 最常见的相等性判断 "==" 使用最频繁,它通常用于对象的值相等性(语义相等)判断,在

  • isArray()函数(JavaScript中对象类型判断的几种方法)

    1) typeof 运算符 typeof 是一元运算符,返回结果是一个说明运算数类型的字符串.如:"number","string","boolean","object","function","undefined"(可用于判断变量是否存在). 但 typeof 的能力有限,其对于Date.RegExp类型返回的都是"object".如: typeof {}; //

  • JS 判断某变量是否为某数组中的一个值的3种方法(总结)

    1.正则表达式 js 中判断某个元素是否存在于某个 js 数组中,相当于 PHP 语言中的 in_array 函数. Array.prototype.in_array=function(e){ var r=new RegExp(','+e+','); return (r.test(','+this.join(this.S)+','));}; 用法如下: var arr=new Array(['b',2,'a',4]); arr.in_array('b');//判断'b'字符是否存在于 arr 数

  • Python判断dict中key是否存在的3种方法实例

    目录 前言 判断方法 第一种方法:使用has_key()方法 第二种方法:使用keys()方法 第三种方法:优雅的使用 in 关键字(Python3支持,Python2不清楚) 总结 前言 今天写代码遇到一个问题,如果要获取字典中某个key的value,那么很简单,直接获取就行了. 但是如果不确定这个字典中是否存在这个key,那直接获取就有可能会报错,那么会有一个KeyError的错误被抛出,当然你也可以直接通过捕获异常的方式来处理这个问题,但我更推荐大家提前判断这个字典中是否有这个key,也就

  • python中调试或排错的五种方法示例

    前言 本文主要给大家介绍了关于python中调试或排错的五种方法,分享出来供大家参考学习,下面话不多说了,来一起看看详细的的介绍吧 python调试或排错的五种方法 1.print,直接打印,比较简单而且粗暴 在代码中直接输入print+需要输出的结果,根据打印的内容判断即可 2.assert断言,很方便,测试人员常常在写自动化用例的时候用的比较多 如下,直接将预期结果和实际结果做判断 def true_code(): x = 3 y = 2 z = x + y assert(5==z), "z

  • Java中避免过多if-else的几种方法

    太多的if-else不太直观,难以维护. 以下面代码为例,展示几种替代if else的方法. String input = "three"; @Test public void testElse() { if ("one".equals(input)) { System.out.println("one"); } else if ("two".equals(input)) { System.out.println("

  • 详解JavaScript类型判断的四种方法

    JavaScript有八种内置类型,除对象外,其他统称为"基本类型". 空值(null) 未定义(undefined) 布尔值(boolean) 数字(number) 字符串(string) 对象 (object) 符号(symbol, ES6中新增) 大整数(BigInt, ES2020 引入) Symbol: 是ES6中引入的一种原始数据类型,表示独一无二的值. BigInt:是 ES2020 引入的一种新的数据类型,用来解决 JavaScript中数字只能到 53 个二进制位(J

  • c#中DataTable转List的2种方法示例

    在项目中常常常使用到DataTable,假设DataTable使用得当,不仅能使程序简洁有用,并且可以提高性能,达到事半功倍的效果,List<T>类是ArrayList类的泛型等效类,该类使用大小可按需动态增加的数组实现IList<T>泛型接口.这篇文章主要介绍了c# DataTable 转 List的两种方法,下面来一起看看吧. 1.  直接写一个datatable转list的类 2. 利用泛型来写,更加通用 public List<Dictionary<string

  • 分享JavaScript 类型判断的几种方法

    目录 一.JavaScript 基本类型 1.原始数据类型 2.引用数据类型 3.两种数据类型的存储方式 二.Javascript 数据类型判断的几种方法 1.typeof 2.instanceof 3.构造函数(constructor) 4.Object.prototype.toString.call() 三.写在最后 一.JavaScript 基本类型 首先介绍一下JavaScript中的八大基本类型 1.原始数据类型 除对象类型(object)以外的其它任何类型定义的不可变的值(值本身无法

  • JavaScript中数组去重常用的五种方法详解

    目录 1.对象属性(indexof) 2.new Set(数组) 3.new Map() 4.filter() + indexof 5.reduce() + includes 补充 原数组 const arr = [1, 1, '1', 17, true, true, false, false, 'true', 'a', {}, {}]; 1.对象属性(indexof) 利用对象属性key排除重复项 遍历数组,每次判断新数组中是否存在该属性,不存在就存储在新数组中 并把数组元素作为key,最后返

随机推荐