Ruby มีออปเปอเรเตอร์ที่น่าสนใจมากมาย ซึ่งรวมถึง:
- Spaceship operator (
<=>) - Modulo assignment operator (
%=) - Triple equals (
===) operator - Greater than (
>) และ Less than (<) - Not equals (
!=)
สิ่งที่คุณอาจไม่ได้รู้คือ ออปเปอเรเตอร์หลายตัวใน Ruby เป็นเมธอดจริงๆ ซึ่งหมายความว่าคุณสามารถ โอเวอร์ไรด์ (overwrite) พฤติกรรมของมัน และใช้สร้างพฤติกรรมแบบกำหนดเองในคลาสของตัวเองได้
ตัวอย่างเช่น การกำหนด == จะบอก Ruby ว่าเปรียบเทียบอ็อบเจ็กต์สองตัวของคลาสเดียวกันอย่างไร
Ruby Logical Operators (ออปเปอเรเตอร์ตรรกะ)
ออปเปอเรเตอร์เหล่านี้ใช้สำหรับ เปรียบเทียบอ็อบเจ็กต์สองตัว และตัดสินใจจากผลลัพธ์
| Operator | คำอธิบาย |
|---|---|
| < | น้อยกว่า |
| > | มากกว่า |
| >= | มากกว่าหรือเท่ากับ |
| <= | น้อยกว่าหรือเท่ากับ |
| == | เท่ากับ |
| != | ไม่เท่ากับ |
| <=> | มากกว่า, เท่ากับ, หรือน้อยกว่า |
ออปเปอเรเตอร์ทั้งหมดเป็นเมธอดและ คืนค่า Boolean ยกเว้น Spaceship operator ที่คืนค่า 1 (มากกว่า), 0 (เท่ากับ), หรือ -1 (น้อยกว่า)
if orange.stock > 20 # ... end
ถ้าต้องการใช้ == กับคลาสของตัวเอง อาจพบว่าไม่ทำงานในตอนแรก เพราะค่าเริ่มต้นใช้ object_id ในการเปรียบเทียบ แก้ไขได้โดยการกำหนดเมธอด == เอง:
class Fruit
attr_reader :name
def initialize(name)
@name = name
end
def ==(other)
name == other.name
end
end
Ruby Arithmetic Operators (ออปเปอเรเตอร์คณิตศาสตร์)
เหมือนกับ == ออปเปอเรเตอร์เหล่านี้ก็เป็นเมธอด จึงสามารถกำหนดพฤติกรรมการบวกอ็อบเจ็กต์สองตัวได้ เช่น Order สองอันบวกกันได้ยอดรวมที่ต้องจ่าย
Modulo operator (%) ให้ผลลัพธ์เป็น เศษจากการหาร มีประโยชน์ในการตรวจสอบเลขคู่/คี่, หารลงตัว, จำกัดค่า ต่างๆ
10 % 2 # 0
Assignment Operators (==, +=, ||=)
ออปเปอเรเตอร์กำหนดค่าเหล่านี้ ไม่ใช่เมธอด มีพื้นฐาน a = 1 และแบบรวม a += 5 (เทียบเท่ากับ a = a + 5)
สองตัวที่พิเศษคือ ||= และ &&=:
a ||= 100หมายถึง "ถ้าaไม่มีอยู่ หรือเป็นfalseหรือnilให้กำหนด 100 ไป มิฉะนั้นคืนค่าaเดิม"
เหมาะสำหรับ Memoization (บันทึกผลการคำนวณที่ช้า)
Unary Operators (ออปเปอเรเตอร์ยูนารี)
ทำงานกับค่าเดียว เช่น +"abc" สร้าง mutable copy ของ frozen string สามารถกำหนดเองได้ด้วย syntax พิเศษ:
class String
def +@
frozen? ? self.dup : self
end
end
!! แปลงค่าใดๆ เป็น Boolean, ! ให้ค่าตรงข้าม
Ruby Splat Operator (*)
แปลง Array เป็นรายการอาร์กิวเมนต์:
attributes = [:title, :author, :category] attr_reader *attributes # เทียบเท่า attr_reader :title, :author, :category
Matching Operator (=~)
ค้นหา index แรกที่ match กับ regex:
"3oranges" =~ /[0-9]/ # 0
!~ คือ NOT match คืนค่า true/false
Ruby Ternary Operator (?:)
เขียน if/else แบบกระชับ: condition ? true_value : false_value
"".size == 0 ? "Empty string" : "Non-empty string"
The Shovel / Push Operator (<<)
เป็นเมธอด พฤติกรรมขึ้นอยู่กับอ็อบเจ็กต์: Array (push), String (append), Integer (left shift)
animals << "cat" "" << "cat" 2 << 1 # 4
Triple Equals Operator (===)
ใช้ใน case statement: String === "bacon" เปรียบเทียบคลาส กำหนด equality ในบริบทของ case
Safe Navigator Operator (&.)
เรียกเมธอดก็ต่อเมื่ออ็อบเจ็กต์ไม่ใช่ nil (Ruby 2.3+):
if user&.active # ... end
Operator Precedence Table (ลำดับความสำคัญ)
Ruby ประเมินโค้ดตามลำดับความสำคัญ (precedence) คล้ายคณิตศาสตร์ ตารางจากสูงไปต่ำ:
| Operators |
|---|
| !, ~, unary + |
| ** |
| unary - |
| *, /, % |
| +, - |
| <<, >> |
| & |
| |, ^ |
| >, >=, <, <= |
| <=>, ==, ===, !=, =~, !~ |
| && |
| || |
| ?, : |
| modifier-rescue |
| =, +=, -=, *=, /=, %= |
| defined? |
| not |
| or, and |
| modifier-if, modifier-unless, modifier-while, modifier-until |
| { } blocks |
| do ... end blocks |
Block precedence อาจทำให้เกิดผลไม่คาดคิด: .map { ... } ทำงานปกติ แต่ .map do ... end อาจคืน Enumerator
Summary
คุณเรียนรู้ออปเปอเรเตอร์ของ Ruby ตั้งแต่คณิตศาสตร์, ตรรกะ, จนถึง unary operators หลายตัวเป็นเมธอดที่นำไปใช้ในคลาสของตัวเองได้ หวังว่าจะมีประโยชน์!