【问题标题】:Adding numerical strings添加数字字符串
【发布时间】:2018-01-17 19:34:49
【问题描述】:

这段代码:

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

打印25。我想知道为什么。我们将2从整数转换为字符串2,所以原则上是2 + 5 = 7。但是为什么输出的是25呢?

【问题讨论】:

  • 没有从一种类型的对象到另一种类型的转换,Ruby 是一种消息传递语言,如下面的答案所述;您将消息#+ 传递给对象var1.to_s,它属于String 类。当您传递消息时,将调用实例(或类)中定义的任何方法:rubylearning.com/blog/2010/11/03/…
  • 另一方面,puts var1 + var2.to_i...

标签: ruby oop


【解决方案1】:

'2' + '5''25',因为 String#+ 连接两个字符串。

如果要进行算术运算,两个操作数都必须是数字,而不是字符串。

【讨论】:

  • 您可以通过var1.to_s.class2.class 来检查对象的类/类型
  • 现在我明白了,感觉就像一个巨大的假人。谢谢@sepp2k!
【解决方案2】:

在 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'

被称为 语法糖 用于普通方法语法:

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

【讨论】:

    【解决方案3】:

    让我们玩得开心

    2 + 5 = 7 
    2.class = Integer
    5.class = Integer 
    
    '2' + '5' = '25'
    '2'.class = String
    '5'.class = 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 语言中调用方法实际上是向对象“发送”消息:

    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 会通过引发错误来保护您。以防万一您或您的同事在您的代码中做一些愚蠢的事情

    但没有什么能阻止您将一种对象类型转换为另一种对象类型

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

    【讨论】:

      猜你喜欢
      • 2016-08-22
      • 1970-01-01
      • 2023-03-30
      • 2021-07-23
      • 1970-01-01
      • 2013-05-07
      • 1970-01-01
      • 2015-01-23
      • 1970-01-01
      相关资源
      最近更新 更多