这段代码:
var1 = 2
var2 = '5'
puts var1.to_s + var2
打印25
。我想知道为什么。我们将2
从整数转换为字符串2
,因此原则上它将是2 + 5 = 7
。但为什么输出25
代替?
答案 0 :(得分:6)
'2' + '5'
为'25'
,因为String#+
会连接两个字符串。
如果要执行算术运算,则两个操作数都需要是数字,而不是字符串。
答案 1 :(得分:0)
在ruby中,代码
x = '2' + '5'
相当于:
x = '2'.+('5')
尝试一下 - 你实际上可以在程序中编写它。第二种语法可能看起来很奇怪,但它符合以下格式:
x = someObject.someMethodName(someArgument)
其中:
someObject => '2' (a String)
someMethodName => +
someArgument => '5' (a String)
是的,+
实际上是String class中方法的名称。因此,您可以检查String类,了解名为+
的方法的工作原理。
语法:
x = '2' + '5'
对于常规方法语法,被称为 syntactic sugar :
x = '2'.+('5')
而且,因为你可以省略括号,你也可以写:
x = '2'.+ '5'
如果您不喜欢String类中名为+
的方法产生的结果,您可以更改它:
class String
def +(other)
return self.to_i + other.to_i
end
end
puts '2' + '5'
--output:--
7
答案 2 :(得分:0)
让我们玩得开心
2 + 5 = 7
2.class = Integer
5.class = Integer
'2' + '5' = '25'
'2'.class = String
'5'.class = String
所以整数+
是数字加
和String +
是连接等价的
......但为什么呢?
你需要理解的是Ruby中的Integer是一个对象而String也是一个对象。所有对象(在任何OOP语言中)都有可以调用它们的方法:
2.public_methods
=> [:%, :&, :*, :+, :-, :/, :<, :>, :^, :|, :~, :-@, :**, :<=>, :<<, :>>, :<=, :>=, :==, :===, :[], :inspect, :size, :succ, :to_int, :to_s, :to_i, :to_f, :next, :div, :upto, ....and the list goes on
'2'.public_methods
=> [:include?, :%, :*, :+, :to_c, :count, :unicode_normalize, :unicode_normalize!, :unicode_normalized?, :partition, :unpack, :unpack1, :sum, :next, ...and the list goes on
实际上当你这样做时:
2 + 5
'2' + '5'
您实际上正在调用方法.+
2.+(5)
'2'.+('5')
但实际上,在OOP语言中调用方法实际上是&#34;发送&#34;给对象的消息:
2.send(:+, 5)
'2'.send(:+, '5')
无论如何,
您需要意识到的一件事是,如果您将不同的对象混合在一起,如:
'2' + 5
# => TypeError: no implicit conversion of Integer into String
2 + '5'
# => TypeError: String can't be coerced into Integer
Ruby会通过引发错误来保护您。万一你或你的colegue在你的代码中做了一些愚蠢的事情
但没有什么能阻止你将一种对象类型转移到另一种对象类型
'2'.to_i + 5
#=> 7
2 + '5'.to_i
# => 7
'2' + 5.to_s
# => '25'
完全OOP语言(如Ruby)的另一个有趣部分是,您可以使用+
方法
class SafePlus
def initialize(first_value)
@first_value = first_value
end
def +(other_value)
@first_value.to_i + other_value.to_i
end
end
SafePlus.new(2) + '5'
# => 7
SafePlus.new("5") + "107"
# => 112
您还可以覆盖String类或Integer类的原始实现,以便所有相应的对象都以这种方式运行:
module MyIntegerFix
def +(other)
super(other.to_i)
end
end
Integer.prepend(MyIntegerFix)
2 + "5"
# => 7
但是为了爱上帝,不要这样做!
为了让你完全迷惑,这是一个令人兴奋的场景,你实际上可以覆盖单个对象
a = "5"
a + "2"
# => "52"
def a.+(other)
self.to_i + other.to_i
end
a + "2"
# => 7
#but
"5" + "2"
# => "52"
所以在这种情况下,我们只是覆盖了一个单个对象,a
对象不是整个String类。
你将无法以这种方式覆盖Integer对象,因为它们是
Singletons
...无法在单个对象基础上覆盖的东西