Ruby มีโอเปอเรเตอร์ที่น่าสนใจมากมาย
ถูกใจ :
- ตัวดำเนินการยานอวกาศ (
<=>
) - ตัวดำเนินการกำหนดโมดูโล (
%=
) - สามเท่ากับ (
===
) โอเปอเรเตอร์ - มากกว่า (
>
) &น้อยกว่า (<
) - ไม่เท่ากับ (
!=
)
สิ่งที่คุณอาจไม่ทราบก็คือตัวดำเนินการเหล่านี้จำนวนมากเป็น วิธี Ruby .
หมายความว่า…
คุณสามารถเขียนทับสิ่งที่พวกเขาทำและใช้เพื่อกำหนดพฤติกรรมที่กำหนดเองในชั้นเรียนของคุณเองได้
ตัวอย่างเช่น โดยการกำหนด ==
คุณสามารถบอก Ruby ถึงวิธีเปรียบเทียบสองวัตถุในคลาสเดียวกันได้
ตอนนี้ :
มาดูตัวอย่างกันเพื่อให้คุณเข้าใจภาพรวมคร่าวๆ ว่าตัวดำเนินการ Ruby เหล่านี้ทำงานอย่างไร &วิธีใช้งาน ในรหัสของคุณ
นี่เป็นหัวข้อสำคัญหากคุณต้องการเข้าใจ Ruby จริงๆ
สารบัญ
- ตัวดำเนินการลอจิก 1 รูบี้
- ตัวดำเนินการเลขคณิต 2 รูบี้
- 3 ผู้ดำเนินการมอบหมาย (==, +=, ||=)
- 4 Unary Operators คืออะไร
- ตัวดำเนินการ Ruby Splat 5 ตัว (พร้อมตัวอย่าง)
- ตัวดำเนินการจับคู่ 6 ตัว (=~)
- 7 Ruby Ternary Operator (ตัวดำเนินการเครื่องหมายคำถาม)
- 8 The Shovel / Push Operator (<<)
- 9 Triple Equals Operator (มากกว่าความเท่าเทียมกัน)
- 10 ตัวดำเนินการ Safe Navigator (&.)
- 11 ตารางลำดับความสำคัญของตัวดำเนินการ
- 12 สรุป
- 12.1 ที่เกี่ยวข้อง
ตัวดำเนินการเชิงตรรกะของทับทิม
อันดับแรก เราจะดูตัวดำเนินการเชิงตรรกะ
คุณสามารถใช้โอเปอเรเตอร์เหล่านี้เพื่อช่วยเปรียบเทียบสองออบเจ็กต์ และตัดสินใจตามผลลัพธ์
นี่คือตาราง:
ตัวดำเนินการ | คำอธิบาย |
---|---|
< | น้อยกว่า |
> | มากกว่า |
>= | มากกว่าหรือเท่ากับ |
<= | น้อยกว่าหรือเท่ากับ |
== | เท่ากับ |
!= | ไม่เท่ากับ |
<=> | มากกว่า เท่ากัน หรือน้อยกว่า |
โอเปอเรเตอร์ทั้งหมดนี้เป็นเมธอด และ ส่งคืนค่าบูลีน ยกเว้นผู้ดำเนินการยานอวกาศ ตัวดำเนินการยานอวกาศส่งกลับค่า 1 (มากกว่า), 0 (เท่ากับ) หรือ -1 (น้อยกว่า)
นี่คือตัวอย่างวิธีการใช้ >
โอเปอเรเตอร์:
if orange.stock > 20 # ... end
หากคุณต้องการใช้คู่เท่ากับ (==
) โอเปอเรเตอร์กับชั้นเรียนของคุณเอง คุณอาจพบว่ามันไม่ได้ผลในตอนแรก…
ตัวอย่าง :
class Fruit def initialize(name) @name = name end end orange1 = Fruit.new("orange") orange2 = Fruit.new("orange") orange1 == orange2 # false
เหตุผลก็คือการใช้งานเริ่มต้นของ ==
คือ BasicObject#==ซึ่งใช้ object_id
วิธีตรวจสอบว่าวัตถุสองชิ้นเหมือนกันหรือไม่
คุณสามารถแก้ไขได้ดังนี้:
class Fruit attr_reader :name def initialize(name) @name = name end def ==(other) name == other.name end end
เรากำลังพูดถึงความหมายของผลไม้สองผลที่เหมือนกัน:
ต้องมีชื่อเดียวกัน
ตัวดำเนินการเลขคณิตทับทิม
ตัวดำเนินการชุดถัดไปคือตัวดำเนินการเลขคณิต
ไม่มีอะไรใหม่ที่นี่…
5 + 5 # 10 10 * 2 # 20 10 ** 2 # 100
แต่เหมือนกับ ==
โอเปอเรเตอร์ นี่คือวิธีการ
สิ่งนี้มีประโยชน์เพราะ คุณสามารถกำหนดความหมายของการเพิ่มสองวัตถุเข้าด้วยกัน .
ดังนั้นถ้าคุณมี Order
. สองรายการ ออบเจ็กต์ การเพิ่มเข้าด้วยกันจะทำให้คุณมีจำนวนเงินที่ต้องชำระทั้งหมด หรือคุณจะได้รับคำสั่งซื้อใหม่ที่เป็นการรวมกันของคำสั่งซื้อทั้งสองนี้
คุณสามารถกำหนดได้ตรง คุณต้องการให้มันทำงานอย่างไรโดยกำหนด +
วิธีการ
โอเปอเรเตอร์อื่นที่คุณอาจไม่คุ้นเคยคือ โอเปอเรเตอร์โมดูโล .
ดูเหมือนเครื่องหมายเปอร์เซ็นต์ (%
)
และสิ่งที่ทำคือให้ส่วนที่เหลือของดิวิชั่น .
ตัวอย่าง :
10 % 2 # 0
โมดูโลโอเปอเรเตอร์มีการใช้งานจริง .มากมาย เช่น การหาว่าตัวเลขเป็นเลขคู่หรือคี่ หากตัวเลขถูกหารด้วยตัวอื่น การจำกัดจำนวน เป็นต้น
ตัวดำเนินการมอบหมาย (==, +=, ||=)
ต่อไปคือโอเปอเรเตอร์การมอบหมาย ซึ่งต่างจากโอเปอเรเตอร์ทั้งหมดที่เราเห็นมาจนถึงตอนนี้ สิ่งเหล่านี้ไม่ใช่วิธีการ
คุณมีโอเปอเรเตอร์การมอบหมายพื้นฐาน:
a = 1
แต่คุณยังมีตัวดำเนินการมอบหมายแบบรวม:
a += 5 # 6 a *= 2 # 12
สิ่งเหล่านี้เทียบเท่ากับการอ่านค่าปัจจุบัน &โดยใช้หนึ่งในตัวดำเนินการเลขคณิตกับมัน จากนั้นบันทึกผลลัพธ์ คุณสามารถทำเช่นนี้กับตัวดำเนินการเลขคณิตทั้งหมด รวมทั้งตัวดำเนินการโมดูโล (%
)
แต่มีโอเปอเรเตอร์การมอบหมายสองตัวที่ทำงานต่างกัน!
นี่คือ ||=
และ &&=
.
ต่างกันเพราะไม่เท่ากัน เป็นเวอร์ชันเลขคณิต
อะไร a ||= 100
เป็นสิ่งนี้:
“ถ้า
a
ไม่มีอยู่จริงหรือหากเป็นfalse
หรือnil
แล้วกำหนด100
ไปที่มันมิฉะนั้นเพียงแค่คืนค่าa
”
นิพจน์ที่ใกล้เคียงที่สุดที่ฉันจะได้รับคือ:
(defined?(a) && a) ? a : a = 100
สิ่งนี้มีประโยชน์หากคุณต้องการบันทึกผลลัพธ์ของการคำนวณที่ช้าหรือคำขอ API ซึ่งเป็นกระบวนการที่เรียกว่า “การบันทึก”
Unary Operators คืออะไร
จนถึงตอนนี้ คุณเคยเห็นตัวดำเนินการที่ทำงานด้วย 2 ค่าเท่านั้น แต่ยังมี ตัวดำเนินการที่ทำงานด้วยค่าเดียวเท่านั้น เราเรียกสิ่งเหล่านี้ว่า “ยูนารีโอเปอเรเตอร์”
ตัวอย่างเช่น :
+"abc"
การดำเนินการนี้จะสร้างสำเนาของสตริงที่ตรึงไว้ไม่แน่นอน
คุณสามารถกำหนดโอเปอเรเตอร์เอกนารีของคุณเองได้ (+
/ -
) แต่คุณต้องมีรูปแบบพิเศษบางอย่าง
ตัวอย่าง :
class String def +@ frozen? ? self.dup : self end end str = "abc".freeze p (+str).frozen? # false
ฉันต้องใช้วงเล็บที่นี่เนื่องจากตัวดำเนินการมีความสำคัญกว่าตัวดำเนินการเอกนารี
มี !!
. ด้วยนะ ซึ่งไม่ใช่วิธีการ:
!!123 # true !!nil # false
อันนี้มีประโยชน์เพราะ จะเปลี่ยนค่าเป็นบูลีน .
แล้วคุณมี !
ซึ่งเหมือนกันแต่ให้ค่าบูลีนตรงข้ามกับคุณ
ตัวอย่าง :
!true # false !!true # true !false # true
ตัวดำเนินการ Ruby Splat (พร้อมตัวอย่าง)
ตัวดำเนินการเครื่องหมาย (*
) น่าสนใจเพราะมันทำสิ่งที่คุณทำไม่ได้หากไม่มีมัน
สมมติว่าคุณมีอาร์เรย์ดังนี้:
attributes = [:title, :author, :category]
และคุณต้องการใช้อาร์เรย์นี้กับวิธีการที่รับอาร์กิวเมนต์ตัวแปร เช่น attr_reader
.
จากนั้นคุณสามารถทำได้:
attr_reader *attributes
ตัวดำเนินการเครื่องหมาย แปลงอาร์เรย์เป็นรายการองค์ประกอบ ดังนั้นมันจึงเหมือนกับการถอดอาร์เรย์และแทนที่ด้วยทุกสิ่งที่อยู่ภายใน
กล่าวอีกนัยหนึ่ง ตัวอย่างสุดท้ายแปลว่า:
attr_reader :title, :author, :category
นั่นคือพลังของตัวดำเนินการ splat 🙂
ตัวดำเนินการจับคู่ (=~)
โอเปอเรเตอร์ Ruby ที่ดูตลกๆ นี้คืออะไร (=~
) ด้วยตัวหนอน?
เป็นโอเปอเรเตอร์ที่ตรงกัน!
ช่วยให้คุณค้นหาดัชนีอย่างรวดเร็วโดยใช้นิพจน์ทั่วไป
นี่คือตัวอย่าง:
"3oranges" =~ /[0-9]/ # 0
ค้นหาตัวเลข &ส่งคืนดัชนีภายในสตริงที่พบการจับคู่ครั้งแรก มิฉะนั้นจะคืนค่าเป็นศูนย์
นอกจากนี้ คุณมี !~
โอเปอเรเตอร์ ซึ่งเป็นโอเปอเรเตอร์ “ไม่ตรงกัน”
ตัวอย่าง :
"abc" !~ /[0-9]/ # false
คุณจะได้รับ true
หรือ false
ด้วยสิ่งนี้ ไม่มีดัชนี ดังนั้นโปรดระลึกไว้เสมอว่า
Ruby Ternary Operator (ตัวดำเนินการเครื่องหมายคำถาม)
ถ้าคุณชอบโค้ดที่กะทัดรัดและสั้น คุณจะต้องหลงรัก Ruby ternary operator
เป็นวิธีการเขียนคำสั่ง if/else แบบกระชับ
หน้าตาเป็นแบบนี้ :
condition ? true : false
นี่คือตัวอย่าง :
"".size == 0 ? "Empty string" : "Non-empty string"
นี่คือวิธีการทำงาน :
ส่วนแรกของโอเปอเรเตอร์ ternary กำหนดเงื่อนไข ("".size == 0
)
แล้วคุณมีสัญลักษณ์เครื่องหมายคำถาม (?
)
หลังจากนั้น คุณจะได้ค่าส่งคืนสำหรับ เมื่อเงื่อนไขนี้เป็นจริง .
แล้วโคลอน (:
)
และส่วนสุดท้ายเป็นค่าส่งคืนสำหรับ เมื่อเงื่อนไขนี้เป็นเท็จ นี่จะเป็น else
ในนิพจน์เงื่อนไขแบบเต็ม
พลั่ว / พลั่ว (<<)
โอเปอเรเตอร์นี้ (<<
) เป็นวิธีการด้วย ดังนั้นมันจึงเปลี่ยนสิ่งที่มันทำขึ้นอยู่กับวัตถุที่คุณกำลังทำงานด้วย
ตัวอย่างเช่น สำหรับอาร์เรย์ เป็นเพียงนามแฝงสำหรับ push
วิธีการ
animals = [] animals << "cat"
ด้วยสตริงจะต่อท้าย:
"" << "cat"
และด้วย Integers
จะทำ "left shift" ซึ่งหมุนบิตทั้งหมดไปทางซ้าย
2 << 1 # 4 2 << 2 # 8 2 << 3 # 16
ตัวดำเนินการ Triple Equals (มากกว่าความเท่าเทียมกัน)
โอเปอเรเตอร์สุดท้ายของเราในวันนี้จะเกี่ยวกับโอเปอเรเตอร์เท่ากับสามเท่า (===
)
วิธีนี้เป็นวิธีหนึ่งเช่นกัน และปรากฏในที่ที่คุณคาดไม่ถึง
ตัวอย่างเช่น ในกรณีคำสั่ง:
case "bacon" when String puts "It's a string!" when Integer puts "It's an integer" end
Ruby กำลังเรียก ===
วิธีการเรียนที่นี่
ชอบสิ่งนี้:
String === "bacon"
สิ่งนี้เปรียบเทียบคลาสปัจจุบันกับคลาสของอ็อบเจ็กต์อื่น
ดังนั้น จุดประสงค์ของโอเปอเรเตอร์นี้คือการกำหนดความเท่าเทียมกัน ในบริบทของคำชี้แจงกรณีศึกษา
ตัวดำเนินการ Safe Navigator (&.)
คุณอาจต้องการเรียกใช้เมธอดบนออบเจ็กต์ แต่อ็อบเจ็กต์นี้อาจ nil
ซึ่งไม่ดีเพราะเรียกเมธอดบน nil
มักทำให้เกิดข้อผิดพลาด
ทางออกเดียว :
if user && user.active # ... end
วิธีที่ดีกว่านี้ :
if user&.active # ... end
&.
นี้ เป็นตัวดำเนินการเนวิเกเตอร์ที่ปลอดภัย (แนะนำใน Ruby 2.3) ซึ่งเรียกเฉพาะ active
วิธีการใน user
ถ้าไม่ใช่ nil
.
มีประโยชน์มาก!
ตารางลำดับความสำคัญของผู้ดำเนินการ
Ruby ประเมินซอร์สโค้ดของคุณตามรายการลำดับความสำคัญ เช่น สิ่งที่เกิดขึ้นในวิชาคณิตศาสตร์ด้วยการคูณและวงเล็บ
นี่อาจเป็นสาเหตุของข้อผิดพลาดทุกประเภทหากคุณไม่เข้าใจวิธีการทำงาน
นี่คือตาราง จากลำดับความสำคัญสูงไปต่ำ :
ตัวดำเนินการ |
---|
!, ~, unary + |
** |
เอกพจน์ - |
*, /, % |
+, - |
<<,>> |
& |
|, ^ |
>,>=, <, <= |
<=>, ==, ===, !=, =~, !~ |
&& |
|| |
?, : |
ตัวแก้ไข-ช่วยเหลือ |
=, +=, -=, *=, /=, %= |
กำหนด? |
ไม่ |
หรือ และ |
ตัวแก้ไข-if, ตัวแก้ไข-เว้นแต่, ตัวแก้ไข-ในขณะ, ตัวแก้ไข-จนถึง |
{ } บล็อก |
ทำ ... จบบล็อก |
ด้วยตัวแก้ไขบางอย่าง มันหมายถึงเวอร์ชันบรรทัดเดียวของคำหลักเหล่านี้
ตัวอย่าง :
puts "awesome" if blog_name == "rubyguides"
ต่อไปนี้คือตัวอย่างที่ลำดับความสำคัญของบล็อกอาจทำให้คุณประหลาดใจ:
# Returns array with uppercase characters p ["a", "b", "c"].map { |character| character.upcase } # Returns Enumerator object p ["a", "b", "c"].map do |character| character.upcase end
ในกรณีแรกมันทำงานตามที่คาดไว้ ในกรณีที่สองบล็อกมีความสำคัญต่ำกว่าดังนั้น map
คิดว่าไม่มีการบล็อก &ส่งคืนตัวแจงนับ
สรุป
คุณได้เรียนรู้เกี่ยวกับโอเปอเรเตอร์หลายตัวของ Ruby ตั้งแต่ตัวดำเนินการเลขคณิต ไปจนถึงตรรกะ &แม้แต่ตัวดำเนินการเอกนารีที่คลุมเครือมากขึ้น
ตัวดำเนินการเหล่านี้เป็นวิธีการที่คุณสามารถใช้ในคลาสของคุณเองได้จริง ๆ
หวังว่าคุณจะพบว่าสิ่งนี้มีประโยชน์และน่าสนใจ!
ขอบคุณที่อ่านนะคะ 🙂