的交換律在Ruby中,我在IRB搞亂了一圈,發現兩個代碼示例,應該工作一樣,但不乘法的紅寶石
"a" * 4 #this is "aaaa"
4 * "a" #this is "String can't be coerced into a Fixnum"
不違反本的交換律乘法?
的交換律在Ruby中,我在IRB搞亂了一圈,發現兩個代碼示例,應該工作一樣,但不乘法的紅寶石
"a" * 4 #this is "aaaa"
4 * "a" #this is "String can't be coerced into a Fixnum"
不違反本的交換律乘法?
它確實違反了交換屬性,但這不一定是個問題,因爲交換屬性適用於數學中複雜的複數。原因"a" * 4
在Ruby中不可交換,因爲在大多數編程語言中,是因爲給定的類型定義了它如何處理運算符。所以,你可以覆蓋*
運營商爲String
和Fixnum
類(但這是在實踐中一個非常非常糟糕的主意):
class String
def *(other)
if other.is_a?(Numeric)
puts "The method was called on an instance of String"
end
end
end
class Fixnum
def *(other)
if other.is_a?(Numeric)
puts "The method was called on an instance of Fixnum"
end
end
end
所以,如果你打電話給
"a" * 4
然後將打印"The method was called on an instance of String"
因爲這相當於"a".*(4)
但這:
4 * "a"
將打印"The method was called on an instance of Fixnum"
因爲4 * "a"
相當於4.*("a")
Here是運營商在Ruby中超載的好文章。
有趣的一面注意:交換性質實際上並不適用於數學中的所有數字,Quaterions和Octonions都不可交換。
編輯
如果你願意,你可以使*
運營商交換(但是這將是一個壞主意)。然後,您可以定義*
交換被叫方和參數喜歡這樣:
class Fixnum
def *(other)
other * self
end
end
這樣,當你永遠有4 * "a"
這將真正做到這一點:"a" * 4
。即使String#*
稍後重新定義,這仍然可以工作。 Monkey patching通常可能有用,但在這種情況下,這是一個可怕的想法,我不建議這樣做,這只是一個很酷的概念證明。
值得注意的是,這就是所有帶有運算符重載的編程語言的工作原理(至少我知道所有這些語言)。所以這不是Ruby特有的怪癖。並+1適當的深入解釋;-) – Carpetsmoker
不,它是一個優先事項和它們都是對象的事實。你在第二個版本中有效地做的是4 *(「a」)。在值爲4的Fixnum實例上調用參數「a」的方法'*'。因此不能強制字符串「a」。
"a" * 4 # repeat 'a' 4 times
4 * "a" # multiply 4 times the string 'a'
除非涉及兩個數字,否則不是乘法。
在Ruby中,一切都是一個對象。 "a"
是String
類的對象,而4
是Fixnum
類的對象。所以偶數就是對象。
而對象可以有方法。
4
有一個名爲*
的方法,它將一個數字作爲參數並將該數字乘以4。此方法不接受字符串作爲參數;它將不會成功地將字符串強制轉換爲數字。 (這就是解釋你的錯誤信息的原因。)
"a"
有一個完全不同的方法,稱爲*
,它將一個數字作爲參數。該方法多次重複該字符串。
因此:
4.*(4) # =>16
"a".*(4) # => "aaaa"
紅寶石,您還可以使用爲*
方法更簡潔的語法:
4 * 4 # =>16
"a" * 4 # => "aaaa"
但它是寫同樣的事情,只是以不同的方式。
乘法的交換性質是一個數學原理。 Ruby是一種編程語言。 *運算符不是乘號,它分別是String和Fixnum類的'*'方法的語法糖。它不會「違反」交換屬性,因爲它不受它的束縛,不僅僅是「印刷」方法受英語語法原理的約束。 –