Ruby在case/when
类型的执行风格上使用===
操作符。现在它也知道Ruby取决于类型,则调用相应的.===
方法。
假设when
语句包含class
名称,则规则为- it will use Module#===, which will return true if the right side is an instance of,
or subclass of, the left side.
。
这里出现instance of
测试
obj = 'hello'
#=> "hello"
case obj
when String
print 'It is a string'
when Fixnum
print 'It is a number'
else
print 'It is not a string'
end
#It is a string
#=> nil
此处出现subclass of
测试
num = 10
#=> 10
case num
when Numeric
puts "Right class"
else
puts "Wrong class"
end
#Right class
#=> nil
现在when
包含String
字面值,然后调用String#=== =,这反过来检查是否在左侧和右侧字面量是否相同(相同序列中的相同字符)。
a = "abc"
#=> "abc"
case a
when "def" then p "Hi"
when "abc" then p "found"
else "not found"
end
#"found"
#=> "found"
所有的逻辑太酷了。现在我的查询是与case/when
结构-
- ruby如何知道
when
是否持有class
或String
字量或在运行时有什么有效的吗?
或
- 在调用相应的
.===
之前执行什么测试
编辑
在理解Case/when
的工作原理之前,让我清除下面的when
在轮到它时所做的事情。
String.===("abc") #=> true
因为"abc"是String
类的实例。-我说的对吗?
现在我试着检查一下谁是谁的超类。
10.class #=> Fixnum
Fixnum.superclass #=> Integer
Integer.superclass #=> Numeric
Numeric.superclass #=> Object
嗯。这意味着下面的代码返回true
,因为Fixnum也是Numeric
的间接子类。-我说的对吗?
Numeric.===(10) #=> true
但是为什么下面的输出与上面的相反呢?
Numeric.===(Fixnum) #=> false
试图更具体到我的查询如下:
当我们调用Numeric.===(10)
和String.===("abc")
。我认为我们发送的不是"abc"
和10
,而是"abc".class
和10.class
。
10.===(10) #=> true
Numeric.===(10) #=> true
现在看看上面的内容。两者都返回true
。它们在相同的逻辑上输出when
0吗?我想是NO
。10.===(10)
就像10 ==(10)
比较。但是Numeric.===(10)
输出true
作为10
的子类,CC_36是Numeric
的子类。
"abc".===("abc") #=> true
String.===("abc") #=> true
现在看看上面的内容。两者都返回true
。它们在相同的逻辑上输出true
吗?我想是NO
。"abc".===("abc")
就像简单的字符串文字比较"abc" ==("abc")
比较。但是String.===("abc")
输出true
为"abc"
, CC_45是String
的一个实例。
现在我的问题是ruby如何检测左侧操作数类型并应用适当的比较规则?
我可能完全错了,那样的话,请纠正我。
我会试着解释@Lee Jarvis也解释过的东西。
class Someclass
end
s = Someclass.new
p s.methods.sort
#[:!, :!=, :!~, :<=>, :==, :===, :=~, :__id__, :__send__, :class, :clone,(...)
看第五种方法。我的Someclass实例有一个无处不在的===
方法。
实际上,它有56个方法,我没有定义其中一个。它们继承自Object;Ruby中的每个类都继承自Object。对于类Object(和我的Someclass), #===实际上与调用#==相同,但是(正如文档所说)#===通常被后代覆盖,以便在case语句中提供有意义的语义。
所以ruby没有做任何聪明的事情,它只是发送一个===
消息(或者调用===
方法,如果你喜欢的话)。
现在我的问题是ruby如何检测左侧操作数类型并应用适当的比较规则?
它不。它只是调用===
方法。就是这样。这就是面向对象的工作方式,并不是Ruby所特有的,所有 OO语言的工作方式都是一样的:在对象上调用方法,对象决定如何反应。(或者,在Ruby、PHP、Java、c#、c++、Python等基于类的语言中,对象的类决定。)
不同的物体可能有不同的反应方式。类检查参数是否为自己的实例,regexp检查参数是否与它们匹配,范围检查参数是否被它们覆盖。
这只是基本的方法分派