1

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

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

而 ifx是一个整数:

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

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

4

3 回答 3

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

  2. Ruby 中的一切都是一个对象,包括 , 的实例StringInteger甚至nil是 . 的 [唯一] 实例NilClass

也就是说,不只是一个 operator *。这是一个简单的旧好方法,在不同的类上声明,由操作员*调用(感谢@SergioTulentsev 的挑剔措辞评论。)这是一个文档String#*,其他你可能会发现。"a" * 6除了:

"a".*(6)

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

于 2017-07-30T14:58:30.007 回答
4

您在这里尝试三种模式:

  • 一个。string * numeric
  • 湾。numeric * string
  • C。numeric * numeric

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

String#*要求第一个参数是数字,其中 a. 满足,并且Numeric#*要求第一个参数是一个数字,c. 满足,并且 b. 才不是。

于 2017-07-30T17:16:16.963 回答
3

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

可以以两种方式之一在对象(例如,"cat"或)上定义方法。1最常见的是该方法是定义在接收者的类上的实例方法*(例如,定义在"cat".class #=> Stringor上1.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”等。例如,“*”、“~”、“[]”和“[]=”是有效的方法名称”

于 2017-07-30T18:23:09.777 回答