現在已經看過幾個運算操作了,最基本的就是+、-、*、/操作,當他們用在數值運算時是較為直覺的加、減、乘、除操作。不過,+在Ruby的物件上,往往可以作串接物件的作用,例如串接字串、串接陣列等,結果都是產生新的物件傳回:
>> "Just" + "in"
=> "Justin"
>> [1, 2] + [3, 4]
=> [1, 2, 3, 4]
>>
=> "Justin"
>> [1, 2] + [3, 4]
=> [1, 2, 3, 4]
>>
*在Ruby上,則通常可以作加倍的動作,例如:
>> "Justin" * 4
=> "JustinJustinJustinJustin"
>> [1, 2] * 4
=> [1, 2, 1, 2, 1, 2, 1, 2]
>>
=> "JustinJustinJustinJustin"
>> [1, 2] * 4
=> [1, 2, 1, 2, 1, 2, 1, 2]
>>
如果要作數值次方運算,則使用**。例如:
>> 9 ** 2
=> 81
>> 9 ** 3
=> 729
>> 9 ** 0.5
=> 3.0
>>
=> 81
>> 9 ** 3
=> 729
>> 9 ** 0.5
=> 3.0
>>
Ruby還提供了關係運算(Rational operation)、邏輯運算(Logical operation)、位元運算(Bitwise operation)等對物件的運算操作:
- 關係運算:如>、>=、<、<=、==、!=、<=>
- 邏輯運算:如and與&&、or與||、not與!
- 位 元運算:如&、|、~、^、>>、<<
- 指 定運算:如+=、-=、*=、/=、%=、&=、|=、~=、^=、>>=、<<=...
其中可作為單元運算的有+、-、~、!等。不僅僅是數值可以使用這些運算操作,在適當的場合,特定的物件也可以使用這些運算操作,例如陣列可以使用&、|來作交集、聯集操作,可以參考 陣列型態 的說明。
Ruby中比較特別的是擁有<=>運算操作,如果左運算元等於右運算元會傳回0,大於傳回1,小於傳回-1。例如:
>> 1 <=> 1
=> 0
>> 1 <=> 2
=> -1
>> 2 <=> 1
=> 1
>>
=> 0
>> 1 <=> 2
=> -1
>> 2 <=> 1
=> 1
>>
在現階段,你可以先知道的是,有些運算操作在物件的動作,其實是可以透過定義方法(Method)來決定該如何進行處理。例如+可以定義+()方法,而%可以定義%()方法:
>> 1.methods
=> [:to_s, :-@, :+, :-, :*, :/, :div, :%, :modulo, :divmod, :fdiv, :**, :abs, :m
agnitude, :==, :===, :<=>, :>, :>=, :<, :<=, :~, :&, :|, :^, :[], :<<, :>>, ..
..略]
>> 1 + 2
=> 3
>> 1.+(2)
=> 3
>> 10 % 3
=> 1
>> 10.%(3)
=> 1
>>
=> [:to_s, :-@, :+, :-, :*, :/, :div, :%, :modulo, :divmod, :fdiv, :**, :abs, :m
agnitude, :==, :===, :<=>, :>, :>=, :<, :<=, :~, :&, :|, :^, :[], :<<, :>>, ..
..略]
>> 1 + 2
=> 3
>> 1.+(2)
=> 3
>> 10 % 3
=> 1
>> 10.%(3)
=> 1
>>
就算是[]索引運算操作,也是可以透過對應的[]()、[]=()來定義:
>> [].methods
=> [:inspect, :to_s, :to_a, :to_ary, :frozen?, :==, :eql?, :hash, :[], :[]=, :at
, :fetch, :first, :last, :concat, :<<, ...略]
>> x = [1, 2, 3]
=> [1, 2, 3]
>> x[1]
=> 2
>> x.[](1)
=> 2
>> x[2]
=> 3
>> x.[](2)
=> 3
>> x[0] = 10
=> 10
>> x.[]=(1, 20)
=> 20
>> x
=> [10, 20, 3]
>>
=> [:inspect, :to_s, :to_a, :to_ary, :frozen?, :==, :eql?, :hash, :[], :[]=, :at
, :fetch, :first, :last, :concat, :<<, ...略]
>> x = [1, 2, 3]
=> [1, 2, 3]
>> x[1]
=> 2
>> x.[](1)
=> 2
>> x[2]
=> 3
>> x.[](2)
=> 3
>> x[0] = 10
=> 10
>> x.[]=(1, 20)
=> 20
>> x
=> [10, 20, 3]
>>
單元運算的方法名稱比較特殊,為運算字元後加上@。例如:
>> -1
=> -1
>> 1.-@()
=> -1
>> +1
=> 1
>> 1.+@()
=> 1
>> ~10
=> -11
>> 10.~@()
=> -11
>> ! true
=> false
>> true.!@()
=> false
>>
=> -1
>> 1.-@()
=> -1
>> +1
=> 1
>> 1.+@()
=> 1
>> ~10
=> -11
>> 10.~@()
=> -11
>> ! true
=> false
>> true.!@()
=> false
>>
要注意,=不能 使用方法定義,所以其它如+=、-=...等也不能使用方法定義,&&與||具有捷徑運算,你也無法用方法定義,因此& &=與||=也無法使用方法定義。可以使用方法定義的運算操作有+、-、*、/、%、[]、[]=、<<、>>、==、 >、<、>=、<=、===、&、|、^、~、!。
初學目前僅需了解到這邊,在了解如何自定義類別之後,將會再介紹如何定義這些特定的方法,事實上,在 陣列型態 中也看過一個自定義 ^ 運算操作的例子:
>> class Array
>> def ^(that)
>> self + that - (self & that)
>> end
>> end
=> nil
>> admins = ["Justin", "caterpillar"]
=> ["Justin", "caterpillar"]
>> users = ["momor", "hamini", "Justin"]
=> ["momor", "hamini", "Justin"]
>> admins ^ users
=> ["caterpillar", "momor", "hamini"]
>>
>> def ^(that)
>> self + that - (self & that)
>> end
>> end
=> nil
>> admins = ["Justin", "caterpillar"]
=> ["Justin", "caterpillar"]
>> users = ["momor", "hamini", "Justin"]
=> ["momor", "hamini", "Justin"]
>> admins ^ users
=> ["caterpillar", "momor", "hamini"]
>>
在使用邏輯運算and與&&、or與||、not與!時,要注意到,在Ruby中,除了nil與false為假之外,其它物件都會被評估為真。例如字串'Justin'在判斷式中會是真,而空字串""也是物件,在判斷式中會是真,所以空陣列是真、空雜湊是真、而0也是真。例如:
>> if 0
>> puts "0"
>> end
0
=> nil
>>
>> puts "0"
>> end
0
=> nil
>>
因此可以利用這個特性,撰寫以下程式:
- main.rb
if ARGV[0]
name = ARGV[0]
else
name = "Guest"
end
puts "Hello, #{name}!"
如果使用者有輸入命令列引數,則ARGV[0]會有字串,就將name設定為使用者指定的命令列引數,否則ARGV[0]會是nil,結果就是判斷為假,就將name設定為"Guest"。例如:
>ruby main.rb Justin
Hello, Justin!
>ruby main.rb
Hello, Guest!
>
Hello, Justin!
>ruby main.rb
Hello, Guest!
>
and與&&、or與||有捷徑運算,and與&&左運算元若判定為假,則就不會繼續運算右運算元,or與||則是左運算元判斷為真,則不的運算右運算元。當判斷確認時停在哪個運算元,就會傳回該運算元,例如:
>> nil && "Justin"
=> nil
>> true && "Justin"
=> "Justin"
>> nil || "Justin"
=> "Justin"
>> "Monica" || "Justin"
=> "Monica"
>>
=> nil
>> true && "Justin"
=> "Justin"
>> nil || "Justin"
=> "Justin"
>> "Monica" || "Justin"
=> "Monica"
>>
利用這個特性,先前的範例程式,可以改寫為以下:
- main.rb
name = ARGV[0] || "Guest"
puts "Hello, #{name}!"