为什么乘法在 Ruby 中并不总是可交换的?



如果x是非整数,我得到这个结果:

x = "a"
x * 6 #=> aaaaaa
6 * x #=> TypeError: String can't be coerced into Fixnum

而如果x是整数:

x = 6
x * 6 #=> 36
6 * x #=> 36

奇怪的是,如果x是非整数,乘法中的操作数顺序很重要,如果x是整数则不重要。有人能解释一下这背后的理性是什么吗?当x是字符串时,为什么变量x必须在*运算符之前以避免引发错误?

  1. 你的后一个片段中有一个错别字:它应该以x = 6开头(不带引号(。

  2. Ruby中的所有东西都是一个对象,包括StringInteger的实例,甚至是nilNilClass的实例。

也就是说,不仅仅是一个运营商*。这是一个普通的老式好方法,在不同的类上声明,由运算符*调用(感谢@SergioTulentsev挑剔的措辞评论。这是String#*的文档,您可能会发现自己的其他文档。"a" * 6别无他法,无非是:

"a".*(6)

您可以在控制台中检查上述内容:这是一个完全有效的 Ruby 代码。因此,不同的类对*方法有不同的实现,因此上面的结果不同。

您在这里尝试三种模式:

  • 一个。string * numeric
  • 二.numeric * string
  • 三.numeric * numeric

方法的行为和需要的参数主要取决于定义方法的方法左侧的内容(在本例中为*(。没有一种方法(包括*(本身是可交换的。

String#*要求第一个参数是数字,a. 满足,Numeric#*要求第一个参数是数字,c. 满足,而 b. 不满足。

您需要了解*的方法的作用。1.这取决于方法的接收器。对于"cat".*(3)来说,"cat"*的接收者。对于1.*(3)(后面解释,可以写成1*3(,1*的接收者。术语"接收方"源自 OOP 向接收方发送消息(方法(的概念。

方法可以通过以下两种方式之一在对象(例如,"cat"1(上定义。最常见的是该方法是在接收方的类上定义的实例方法(例如,*"cat".class #=> String1.class #=> Integer上定义的。第二种方法(此处不适用(是该方法已在对象的单例类上定义,前提是对象有一个。("cat"有一个单例类,但1,作为一个直接值,没有。

因此,当我们看到"cat".*(3)时,我们查看文档中的 String#* 并得出结论:

"cat".*(3) #=> "catcatcat"

对于1*(3),我们查看 Integer#*,它告诉我们

1.*(3) #=> 3

让我们尝试另一个:[1,2,3].*(3),因为[1,2,3].class #=> Array我们查看 Array#* 并得出结论

[1,2,3].*(3) #=> [1, 2, 3, 1, 2, 3, 1, 2, 3]

请注意,此方法有两种形式,具体取决于其参数是整数(如此处(还是字符串。在后一种情况下

[1,2,3].*(' or ') #=> "1 or 2 or 3"

许多方法具有不同的行为,具体取决于其参数(以及是否提供可选块(。

最后,Ruby 允许我们使用这三种方法的速记(以及某些其他方法的名称由不是字母、数字或下划线的字符组成(:

"cat"*3     #=> "catcatcat"
"cat" * 3   #=> "catcatcat"
1*3         #=> 3
[1,2,3] * 3 #=> [1, 2, 3, 1, 2, 3, 1, 2, 3]

这种速记通常被称为"句法糖"。

1 Ruby 的方法名称不限于单词,例如 "map"、"upcase" 等等。例如,"*"、"~"、"[]"和"[]="是有效的方法名称">

最新更新