ประเภทคลาส Ruby และคำสั่ง case


138

อะไรคือความแตกต่างระหว่าง

case item.class
when MyClass
  # do something here
when Array
  # do something different here
when String
  # do a third thing
end

และ

case item.class
when MyClass.class
  # do something here
when Array.class
  # do something different here
when String.class
  # do a third thing
end

ด้วยเหตุผลบางประการงานแรกเหล่านี้บางครั้งและครั้งที่สองไม่ทำงานและในบางครั้งงานที่สองใช้งานได้และงานแรกไม่ทำงาน ทำไม? วิธีใดเป็นวิธีที่ "เหมาะสม" ในการทำ


1
สตริงคือคลาส คลาสของคลาสคือคลาส
Volte

โปรดทราบว่าMyClass === objใช้เมธอดModule # ===เพื่อตรวจสอบว่าobjเป็นอินสแตนซ์ของMyClass.
sergio 郝海东冠状病六四事件法轮功

คำตอบ:


237

คุณต้องใช้:

case item
when MyClass
...

ฉันมีปัญหาเดียวกัน: จะจับ Errno :: ECONNRESET class ใน "case when" ได้อย่างไร?


1
ขอบคุณ! ขออภัยที่หลอกลวง (หรือประเภทของการหลอกลวง) แต่การค้นหาหลายครั้งไม่ได้ตอบคำถามก่อนหน้านั้น ดูเหมือนว่าการใช้ === โดยคำสั่ง case นั้นค่อนข้างเป็นปัญหาที่พบบ่อยตอนนี้ฉันเห็นว่านี่คือปัญหา สิ่งนี้ควรได้รับการชี้ให้เห็นบ่อยขึ้นในแบบฝึกหัดและอื่น ๆ (แต่ฉันพนันได้เลยว่าผู้เขียนบทช่วยสอนหลายคนไม่ทราบเรื่องนี้)
Daisy Sophia Hollman

4
ข้อแม้ที่ไม่ได้กล่าวถึงหากใช้ ActiveRecord เมธอด ActiveRecord === ในการเปรียบเทียบคลาสใช้. is_a? ซึ่งหมายความว่าคลาสย่อยของคลาสจะประเมินเป็นจริงในคำสั่ง case github.com/rails/rails/blob/…
Jeremy Baker

63

ใช่ Nakilon ถูกต้องคุณต้องรู้ว่าตัวดำเนินการ threequal === ทำงานอย่างไรกับวัตถุที่ระบุในไฟล์ whenประโยคอย่างไร ใน Ruby

case item
when MyClass
...
when Array
...
when String
...

เป็นเรื่องจริง

if MyClass === item
...
elsif Array === item
...
elsif String === item
...

เข้าใจว่า case เรียก method threequal ( MyClass.===(item)ตัวอย่าง) และ method นั้นสามารถกำหนดให้ทำอะไรก็ได้ที่คุณต้องการจากนั้นคุณสามารถใช้ case statement ด้วยความแม่นยำ


1
ถ้าฉันarr = []สังเกตแล้วว่าif Array === arrจะประเมินเป็นจริง แต่if arr === Arrayจะประเมินเป็นเท็จ ใครช่วยอธิบายหน่อยได้ไหม
Daniel

5
=== เป็นเพียงวิธีการที่สามารถกำหนดให้ทำอะไรก็ได้ที่นักออกแบบของคลาสต้องการให้ทำ จำไว้ด้วยว่า a === b หมายถึง a จริงๆ === b ดังนั้นหากคุณสลับ a และ b ไปรอบ ๆ คุณจะได้รับพฤติกรรมที่แตกต่างกัน ไม่มีการรับประกันว่า === เป็นการสับเปลี่ยน ในความเป็นจริง Array === Array เป็นเท็จ แต่ Object === Object เป็นจริงดังนั้น Array จึงกำหนดความหมายของ === ใหม่
Fred

14

คุณสามารถใช้ได้:

case item.class.to_s
    when 'MyClass'

... เมื่อบิดต่อไปนี้ไม่ได้:

case item
    when MyClass

เหตุผลของเรื่องนี้ก็คือว่าcaseการใช้งาน===และความสัมพันธ์===ผู้ประกอบการอธิบายคือไม่สับเปลี่ยน ยกตัวอย่างเช่น5เป็นIntegerแต่? นี้เป็นวิธีที่คุณควรคิด/Integer5casewhen


5

ใน Ruby ชื่อคลาสคือค่าคงที่ที่อ้างถึงอ็อบเจ็กต์ประเภทClassที่อธิบายคลาสเฉพาะ นั่นหมายความว่าการพูดMyClassใน Ruby นั้นเทียบเท่ากับการพูดMyClass.classใน Java

obj.classเป็นวัตถุประเภทที่Classอธิบายคลาสของobj. ถ้าobj.classเป็นMyClassเช่นนั้นobjถูกสร้างขึ้นโดยใช้MyClass.new(พูดโดยประมาณ) MyClassเป็นวัตถุประเภทClassที่อธิบายถึงวัตถุใด ๆ ที่สร้างโดยใช้MyClass.newที่สร้างขึ้นโดยใช้

MyClass.classเป็นคลาสของMyClassอ็อบเจ็กต์ (เป็นคลาสของอ็อบเจ็กต์ประเภทClassที่อธิบายอ็อบเจ็กต์ใด ๆ ที่สร้างโดยใช้MyClass.new) กล่าวอีกนัยหนึ่งMyClass.class == Class.


1

ขึ้นอยู่กับลักษณะของitemตัวแปรของคุณ ถ้าเป็นตัวอย่างของวัตถุเช่น

t = 5

แล้ว

t.class == Fixnum

แต่ถ้าเป็นคลาสในตัวเองเช่น

t = Array

มันจะเป็นClassวัตถุดังนั้น

t.class == Class

แก้ไข : โปรดอ้างอิงถึงHow to catch Errno :: ECONNRESET class ใน "case when"? ตามที่ Nakilon ระบุไว้เนื่องจากคำตอบของฉันอาจผิด


ใน Ruby ทุกอย่างเป็น "ตัวอย่างของวัตถุ"
Eric Duminil
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.