การกำหนดประเภทของวัตถุในทับทิม


364

ฉันจะใช้ python เป็นตัวอย่างของสิ่งที่ฉันกำลังมองหา (คุณสามารถคิดว่ามันเป็น pseudocode หากคุณไม่รู้จัก Python):

>>> a = 1
>>> type(a)
<type 'int'>

ฉันรู้ในทับทิมฉันสามารถทำ:

1.9.3p194 :002 > 1.class
 => Fixnum 

แต่นี่เป็นวิธีที่เหมาะสมในการกำหนดประเภทของวัตถุหรือไม่


5
@ JörgWMittag แต่ AFAICR นั่นเป็นสิ่งที่ `type 'ทำใน Python แม้ว่าหน่วยความจำของฉันจะคลุมเครือ คุณต้องการisinstance หรือตรวจสอบการตอบกลับ แต่เพียงแค่พูดว่า "ไม่มี !!!" ไม่เป็นประโยชน์จริง ๆ ตอนนี้ใช่ไหม พิจารณาการศึกษาแทน
Dave Newton

4
@ JörgWMittagในขณะที่ฉันเห็นใจ OP ให้รหัสเพื่อเลียนแบบใน Ruby ถ้าคุณไม่ให้ความรู้กับ OP ว่าเสียงดังไม่มีประโยชน์ IMO และแม้ว่าคุณจะทำเช่นนั้นมันอาจเป็นข้อมูลเท่านั้นเนื่องจาก OP กำหนดว่าเขา / เธอต้องการรหัสผ่าน
Dave Newton

5
@ JörgWMittag - ใน Ruby ทุกอย่างเป็น Object ดังนั้นจึงไม่มีประเภทดั้งเดิมเนื่องจากมีอยู่ใน Python (int, long, boolean เป็นต้น) ดังนั้นภายใน Ruby คลาสจึงเป็นนิยามประเภท สิ่งนี้ไม่ได้ จำกัด เฉพาะ Ruby ทั้งคำว่า class และ type นั้นมีความหมายเหมือนกันในหลาย ๆ ภาษาและมีความหมายกว้างกว่าในทฤษฎี OOP
ocodo

6
เนื่องจากเรากำลังพูดถึง Ruby จริงๆที่นี่ประเภทและคลาสมีความหมายเหมือนกันจึงไม่มีข้อโต้แย้งเกี่ยวกับเรื่องนี้ค่าทั้งหมดเป็นวัตถุ ดังนั้นสำหรับใครก็ตามที่พูดถึง Ruby คลาสจะเป็นประเภท - อ้างอิง: ruby-lang.org/en/about
ocodo

2
@ JörgWMittagบทความนี้ค่อนข้างให้ข้อมูลและฉันจะอ่านส่วนที่เหลือเมื่อฉันมีโอกาส โดยเฉพาะอย่างยิ่งคุกดูเหมือนจะเป็นปล้องค่อนข้างดี (และมีความรู้พื้นหลังมากขึ้นกว่าที่ฉันมี) ทำไมมันไม่ถูกต้องไปเรียกร้อง (เป็นหนึ่งในอาจารย์ของฉันได้) ที่ Python, Ruby และภาษาแบบไดนามิกพิมพ์อื่น ๆ "ไม่ได้จริงๆวัตถุ ที่มุ่งเน้น "(สิ่งที่เขาอาจหมายถึงโดยไม่ทราบว่าเป็นเพราะพวกเขาไม่ได้มุ่งเน้น ADT) แต่ Ruby ไม่ได้ถูกพิมพ์แบบคงที่ดังนั้นจึงไม่มี ADT ในแง่ที่ Cook กำลังอธิบายดังนั้นการคัดค้านของคุณบนพื้นฐานของความแตกต่างนั้นจะไม่เป็นประโยชน์
Kyle Strand

คำตอบ:


607

วิธีที่เหมาะสมในการกำหนด "ประเภท" ของวัตถุซึ่งเป็นคำที่สั่นคลอนในโลกทับทิมคือการเรียก object.classของวัตถุซึ่งเป็นระยะสั่นคลอนในโลกของทับทิมคือการเรียก

เนื่องจากคลาสสามารถสืบทอดจากคลาสอื่น ๆ ได้ถ้าคุณต้องการตรวจสอบว่าวัตถุนั้นเป็น "ชนิดใดชนิดหนึ่ง" หรือไม่คุณอาจobject.is_a?(ClassName)ต้องเรียกดูว่าobjectเป็นประเภทใดClassNameหรือได้มาจากหรือไม่

การตรวจสอบชนิดปกติไม่ได้ทำใน Ruby แต่จะมีการประเมินวัตถุแทนตามความสามารถในการตอบสนองต่อวิธีการบางอย่างโดยทั่วไปเรียกว่า "การพิมพ์เป็ด " " กล่าวอีกนัยหนึ่งถ้ามันตอบสนองต่อวิธีการที่คุณต้องการไม่มีเหตุผลที่เฉพาะเจาะจงเกี่ยวกับประเภท

ตัวอย่างเช่นobject.is_a?(String)เข้มงวดเกินไปเนื่องจากคลาสอื่นอาจใช้วิธีการที่แปลงเป็นสตริงหรือทำให้มันทำงานเหมือนกันกับวิธีการทำงานของสตริง object.respond_to?(:to_s)จะเป็นวิธีที่ดีกว่าในการทดสอบว่าวัตถุที่เป็นปัญหาทำในสิ่งที่คุณต้องการ


13
-1 #classไม่ได้ส่งกลับชนิดของวัตถุที่จะส่งกลับของชั้น ชื่อควรเป็นของแจกที่ตายแล้ว คลาสและประเภทเป็นแนวคิดที่แตกต่างกันสองอย่างใน OO
Jörg W Mittag

78
@ Jörg W Mittag: ฉันไม่เห็นด้วย "คลาส" และ "ความเร็วโปรเซสเซอร์" (เพื่อเลือกตัวอย่าง) เป็นแนวคิดที่แตกต่างกันสองประการ แต่ "คลาส" และ "ประเภท" เป็นแนวคิดที่เกี่ยวข้องอย่างใกล้ชิด ตัวอย่างเช่นนี่คือสิ่งที่บทความ Wikipedia ในชั้นเรียนกล่าวว่า: "ในการเขียนโปรแกรมเชิงวัตถุคลาสเป็นโครงสร้างที่ใช้เพื่อกำหนดประเภทที่แตกต่าง" tadman เป็นประโยชน์กับผู้ถาม
Teemu Leisti

18
@ JörgWMittagในทับทิมสิ่งที่ใกล้กับtypeofจาก C, JavaScript classและคนอื่น ไม่มีระบบโปรโตคอลอย่างเป็นทางการใน Ruby เหมือนในภาษาอื่น ๆ Objective-C เป็น Smalltalk ที่ใกล้เคียงที่สุดเมื่อเทียบกับสิ่งนั้น หากคุณกำลังกำหนด "ประเภท" เป็น "วัตถุซึ่งตอบสนองต่อชุดวิธีการเฉพาะพร้อมผลลัพธ์ที่ยอมรับได้" ก็ไม่มีทางยืนยันได้เลย มันหลวมเกินไป ส่วนใหญ่ใน Ruby เมื่อพูดถึงประเภทของวัตถุก็เข้าใจว่าคุณกำลังพูดถึงชั้นเรียน ฉันใช้ประเภทคำในเครื่องหมายคำพูดด้วยเหตุผลอย่างนั้น
tadman

14
@ Jörg W Mittag: ฉันยืนยันต่อไปว่า "คลาส" และ "ประเภท" นั้นไม่แตกต่างกันอย่างสิ้นเชิงแนวคิดใน OO ตามที่แสดงโดยอ้าง (นอกจากนี้: วิธีการทำคุณประกาศตัวแปรใน Java โดยการให้? ทั้งประเภทหรือระดับของตัวแปรตามด้วยชื่อของมัน " int i" หรือ " Integer j".) Tadman ตอบคำถามในลักษณะที่ดูเหมือนจะตอบสนองทั้งผู้ถามที่ และผู้ชมทั่วไปในขณะที่ชี้แจงคำศัพท์ที่ Ruby ใช้ ฉันไม่มีความสนใจในการเข้าร่วมการศึกษาเชิงวิชาการเกี่ยวกับคำศัพท์เชิงวัตถุดังนั้นโปรดมีคำสุดท้าย
Teemu Leisti

11
@TeemuLeisti ปัญหาส่วนใหญ่ที่นี่มาจากความจริงที่ว่าทุกอย่างใน Ruby เป็นวัตถุและมีคลาสในขณะที่ในภาษาอื่นทุกภาษามีประเภทดั้งเดิมที่ไม่ใช่วัตถุและไม่มีคลาสตรงกันข้ามกับวัตถุที่ทำ เมื่อไม่มีสิ่งใดที่บริสุทธิ์และไม่มีหนทางใดที่จะนิยามอย่างเป็นทางการความหมายจะกลายเป็นฝ้ามัวในโลกทับทิมโดยเฉพาะ Matz ไม่ยึดมั่นในโรงเรียนแห่งความคิดใด ๆ โดยเฉพาะที่นี่นอกจากของเขา
tadman


44

บ่อยครั้งในทับทิมคุณไม่สนใจว่าคลาสของวัตถุจะเป็นอย่างไรต่อไปคุณแค่สนใจว่ามันตอบสนองต่อวิธีการบางอย่าง สิ่งนี้เรียกว่าการพิมพ์เป็ดและคุณจะเห็นมันในทุกประเภทของรหัสฐานทับทิม

ดังนั้นในหลาย ๆ กรณี (ถ้าไม่ใช่มากที่สุด) วิธีที่ดีที่สุดในการใช้ Duck Typing โดยใช้#respond_to?(method):

object.respond_to?(:to_i)

1
จุดที่ถูกต้อง ไม่ตอบคำถาม แต่กระทบจิตใจของคำถาม
user566245

@ user566245 ตอบสนองได้ดีหรือไม่ (: the_question) แต่อย่างที่คุณบอกว่าไม่ตอบคำถามเพียงแค่ให้ข้อมูลที่เกี่ยวข้อง ค่อนข้างแน่ใจว่าคำตอบจำเป็นต้องตอบคำถาม
R. Rincón

17

ฉันจะพูดว่า "ใช่" ในฐานะที่เป็น "Matz" ได้พูดบางสิ่งเช่นนี้ในหนึ่งในการพูดคุยของเขา "วัตถุทับทิมไม่มีประเภท ไม่ใช่ทั้งหมด แต่เป็นส่วนที่เขาพยายามจะข้ามมาหาเรา ทำไมทุกคนจะพูดว่า "ทุกอย่างเป็นวัตถุ" แล้ว? เพื่อเพิ่มเขากล่าวว่า "ข้อมูลมีประเภทไม่ใช่วัตถุ"

ดังนั้นเราอาจสนุกกับสิ่งนี้

https://www.youtube.com/watch?v=1l3U1X3z0CE

แต่รูบี้ไม่สนใจเกี่ยวกับประเภทของวัตถุเพียงแค่คลาส เราใช้คลาสที่ไม่ใช่ประเภท ข้อมูลทั้งหมดนั้นมีคลาส

12345.class

'my string'.class

พวกเขาอาจมีบรรพบุรุษ

Object.ancestors

พวกเขามีคลาสเมตาดาต้า แต่ฉันจะช่วยคุณบันทึกรายละเอียดไว้

เมื่อคุณรู้จักชั้นเรียนแล้วคุณจะสามารถค้นหาวิธีการที่คุณอาจใช้ นั่นคือสิ่งที่ต้องการ "ชนิดข้อมูล" หากคุณต้องการดูรายละเอียดจริงๆลองมองหา ...

"โมเดลวัตถุทับทิม"

นี่เป็นคำที่ใช้สำหรับวิธีที่ Ruby จัดการกับวัตถุ มันเป็นแบบภายในทั้งหมดดังนั้นคุณจะไม่เห็นสิ่งนี้มากนัก แต่ก็ดีที่จะรู้ แต่นั่นเป็นหัวข้ออื่น

ใช่ คลาสเป็นชนิดข้อมูล วัตถุมีคลาสและข้อมูลมีชนิด ดังนั้นถ้าคุณรู้เกี่ยวกับฐานข้อมูลแล้วคุณจะรู้ว่ามีชุดของประเภทที่ จำกัด เท่านั้น

หมายเลขบล็อกข้อความ


ตัวอย่างเช่นObject.ancestors # => [Object, Kernel, BasicObject]
Dorian
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.