Ruby มีคีย์เวิร์ด defined? ที่ช่วยตรวจสอบว่าตัวแปรถูกนิยามหรือไม่
ถ้าตัวแปรมีอยู่ คุณจะได้ type ของมัน:
apple = 1 defined?(apple) # "local-variable"
ถ้าไม่มี จะได้ nil:
defined?(bacon) # nil
เหมือน operator typeof ของ JavaScript หากต้องการรู้ class ของออบเจกต์ ใช้เมธอด class แทน
จุดน่าสนใจบางจุด:
defined?เป็น คีย์เวิร์ด ไม่ใช่ เมธอดdefined?เป็นหนึ่งในสิ่งน้อยใน Ruby ที่ลงท้ายด้วยเครื่องหมายคำถาม แต่ไม่ปฏิบัติตาม convention ที่คืนtrueหรือfalsedefined?แยกแยะได้ระหว่างค่า nil กับตัวแปรที่ไม่เคยถูกตั้งค่า
ลักษณะพิเศษเหล่านี้ทำให้คีย์เวิร์ดนี้คุ้มค่าที่จะเรียนรู้
วิธีที่ดีกว่าในการตรวจสอบตัวแปรที่นิยามแล้ว
คีย์เวิร์ดนี้มีประโยชน์ แต่มีปัญหาบางอย่าง
ทำไม?
เพราะ operator precedence ต่ำ
หากคุณทำแบบนี้:
defined? orange && orange.size
ผลลัพธ์คือ "expression"
เพราะ orange && orange.size ถูกตีความเป็นอาร์กิวเมนต์ของ defined?
วิธีที่ถูกต้องคือ:
defined?(orange) && orange.size
Ruby มีวิธีอื่นในการตรวจสอบว่าตัวแปรถูกนิยามหรือไม่
สำหรับ local variables:
local_variables.include?(:orange)
สำหรับ instance variables:
instance_variable_defined?("@food")
แตคุณไม่ควรใช้สิ่งเหล่านั้น
ใน 99% ของกรณี หาก local variable หายไป หมายถึงคุณ typo หรือใครลืมนิยามตัวแปรนั้น
instance variables แล้วล่ะ?
Instance variables ที่ไม่ได้นิยามจะเป็น nil เสมอ ดังนั้นคุณอยากตรวจสอบนั่น
ลอง "safe navigator operator" (Ruby 2.3+) ซึ่งเรียกเมธอดก็ต่อเมื่อตัวแปรไม่ใช่ nil
ตัวอย่าง:
if @user&.country == "Spain" # ... end
สิ่งนี้เทียบเท่ากับ:
if @user && @user.country == "Spain" # ... end
วิธีเหล่านี้ไม่ universal เท่า defined? แต่ predictable กว่าและ error-prone น้อยกว่า
ตรวจสอบว่าเมธอดถูกนิยามหรือไม่
คุณสามารถใช้ defined? ตรวจสอบเมธอดได้ แต่ไม่ค่อย practical
ตัวอย่าง:
defined?(puts) # "method"
เพราะมันเป็นคีย์เวิร์ด ไม่ใช่เมธอด คุณไม่สามารถใช้กับออบเจกต์ได้
นี่คือสิ่งที่ผมหมายถึง:
[].defined?(:size) # undefined method `defined?' for []:Array
คุณกำลังหาเมธอด respond_to?
วิธีใช้:
[].respond_to?(:size) # true [].respond_to?(:orange) # false
ตรวจสอบว่าคลาสมีอยู่หรือไม่
ตัวอย่าง:
defined?(Object) # "constant" defined?(A) # nil
ตัวเลือกที่ดีกว่าคือใช้เมธอด const_defined?
แบบนี้:
Object.const_defined?(:String) # true Object.const_defined?(:A) # false
สรุป
คุณเรียนรู้วิธีง่ายๆ ในการตรวจสอบว่าตัวแปร คลาส หรือเมธอดมีอยู่จริง!
เมื่อทำงานกับตัวแปร สิ่งที่คุณต้องการส่วนใหญ่คือตรวจสอบ nil แทนการตรวจสอบว่าตัวแปรนิยามหรือไม่ หรือดีกว่านั้น แปลงตัวแปรเป็นคลาสที่รู้จักด้วย conversion method
หวังว่าบทความนี้จะมีประโยชน์! หากเป็นเช่นนั้นกรุณา แชร์ ให้ผู้คนอีกมากขึ้นได้เพลิดเพลินไปกับมัน