添加数字字符串

时间:2018-01-17 19:34:50

标签: ruby oop

这段代码:

var1 = 2
var2 = '5'    
puts var1.to_s + var2

打印25。我想知道为什么。我们将2从整数转换为字符串2,因此原则上它将是2 + 5 = 7。但为什么输出25代替?

3 个答案:

答案 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 ...无法在单个对象基础上覆盖的东西