มิกซ์อินหรือลักษณะนิสัยดีกว่าการรับมรดกหลายแบบธรรมดาอย่างไร


54

C ++ มีการสืบทอดหลายแบบธรรมดาการออกแบบหลายภาษานั้นห้ามมิให้มีอันตราย แต่ภาษาบางภาษาเช่น Ruby และ PHP ใช้ไวยากรณ์แปลก ๆ เพื่อทำสิ่งเดียวกันและเรียกว่า mixins หรือลักษณะ ฉันได้ยินมาหลายครั้งแล้วว่ามิกซ์อิน / คุณลักษณะนั้นยากต่อการทารุณมากกว่าการถ่ายทอดทางพันธุกรรมที่หลากหลาย

อะไรที่ทำให้พวกเขามีอันตรายน้อยลง? มีบางสิ่งที่เป็นไปไม่ได้สำหรับ mixins / traits แต่เป็นไปได้ด้วย C ++ - กำหนดลักษณะการสืบทอดหลาย ๆ แบบ? เป็นไปได้ที่จะพบปัญหาเพชรกับพวกเขาหรือไม่?

ดูเหมือนว่าเราใช้มรดกหลายอย่าง แต่เพียงแค่แก้ตัวว่ามันเป็นส่วนผสม / คุณลักษณะเพื่อให้เราสามารถใช้มันได้


7
หวังว่าจะมีใครบางคนโพสต์คำตอบที่ดีเขียนอย่างรอบคอบและละเอียดถี่ถ้วนเพื่อคนนี้
Robert Harvey

7
Ruby และ PHP ไม่ได้แนะนำมิกซ์และลักษณะ Mixins ถูกนำมาใช้ใน Flavours (1980) ลักษณะถูกนำมาใช้ใน Squeak Smalltalk (2001) Flavours เป็นภาษาเชิงวัตถุแรกที่มีการสืบทอดหลายแบบและใช้ mixins C ++ มีการสืบทอดหลายรุ่นในเวอร์ชัน 2.0 ซึ่งเปิดตัวในปี 1989 9 ปีหลังจาก Flavours ดังนั้นคำถามควรเป็น: Flavours มีมิกซ์เรียบง่าย แต่ภาษาบางภาษาเช่น C ++ ได้แนะนำไวยากรณ์ที่แปลกประหลาดในการทำสิ่งเดียวกันและเรียกมันว่าการสืบทอดหลายอย่าง
Jörg W Mittag

คำตอบ:


31

มีจำนวนของปัญหาเกี่ยวกับมรดกหลายเมื่อมันถูกนำมาใช้กับการเรียนเต็มเปี่ยมพวกเขาทั้งหมดหมุนรอบมี แต่ความคลุมเครือ

ความกำกวมปรากฏในหลายวิธี:

  1. หากคุณมีคลาสฐานสองคลาสที่มีเขตข้อมูลเดียวกันxและชนิดที่ได้รับมาขอให้xมันได้อะไร
    • หากxตัวแปรทั้งสองมีชนิดที่ไม่สอดคล้องกันคุณสามารถอนุมานได้
    • หากเป็นประเภทเดียวกันคุณสามารถลองรวมมันเข้ากับตัวแปรเดียวกันได้
    • คุณสามารถเปิดเผยพวกเขาเป็นชื่อที่ผ่านการรับรองแบบแปลก ๆ ได้เสมอ
  2. หากคุณมีสองฐานเรียนกับฟังก์ชั่นเดียวกันfที่มีลายเซ็นเหมือนกันและมีคนเรียกfซึ่งได้รับเรียกว่า?
    • จะเกิดอะไรขึ้นถ้าคลาสพื้นฐานสองคลาสแบ่งใช้บรรพบุรุษเสมือนทั่วไปอีกตัว (ปัญหาเพชร)
    • จะเกิดอะไรขึ้นถ้าฟังก์ชั่นนั้นแตกต่างกัน แต่ลายเซ็นที่เข้ากันได้
  3. เมื่อคุณสร้างคลาสที่มีคลาสพื้นฐานสองคลาสตัวสร้างคลาสพื้นฐานใดที่เรียกว่าอันดับแรก เมื่อคุณทำลายวัตถุที่ถูกฆ่าตาย?
  4. เมื่อคุณจัดโครงสร้างวัตถุในหน่วยความจำคุณจะทำมันอย่างไรอย่างสม่ำเสมอ?
  5. คุณจะจัดการกรณีเหล่านี้ทั้งหมดด้วยคลาสพื้นฐาน 3 คลาสได้อย่างไร 10?

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

ลักษณะหรือส่วนประสม (หรืออินเทอร์เฟซหรือ ... ) เป็นโครงสร้างทั้งหมดที่จำกัดความสามารถของประเภทเฉพาะเพื่อไม่ให้มีความกำกวม พวกเขาไม่ค่อยมีอะไรเป็นของตัวเอง สิ่งนี้ทำให้องค์ประกอบของประเภทราบรื่นขึ้นเพราะไม่มีตัวแปรสองตัวหรือฟังก์ชั่นสองอย่าง ... มีตัวแปรและการอ้างอิง ฟังก์ชั่นและลายเซ็น คอมไพเลอร์รู้ว่าต้องทำอะไร

วิธีการทั่วไปอื่น ๆ ที่นำมาใช้คือการบังคับให้ผู้ใช้ "สร้าง" (หรือผสม) ของพวกเขาทีละประเภท แทนที่จะเป็นคลาสพื้นฐานที่เป็นพาร์ทเนอร์เท่ากันในประเภทใหม่คุณเพิ่มประเภทหนึ่งไปยังอีกประเภทหนึ่ง - แทนที่สิ่งใดก็ตามที่อยู่ที่นั่น (โดยปกติจะมีไวยากรณ์ที่เป็นทางเลือกเพื่อตั้งชื่อใหม่และ / หรือเปิดเผยบิตที่แทนที่)

มีบางสิ่งที่เป็นไปไม่ได้สำหรับ mixins / traits แต่เป็นไปได้ด้วย C ++ - กำหนดลักษณะการสืบทอดหลาย ๆ แบบ?

ขึ้นอยู่กับภาษา - โดยทั่วไปจะกลายเป็นปัญหาหรือเป็นไปไม่ได้ที่จะรวมการใช้งานของฟังก์ชั่นและการจัดเก็บสำหรับตัวแปรจากหลายคลาสฐานและเปิดเผยพวกเขาในประเภทที่ได้รับ

เป็นไปได้หรือไม่ที่จะพบปัญหาเพชรกับพวกเขา?

รูปแบบที่รุนแรงน้อยกว่าบางครั้งจะปรากฏขึ้นตามภาษาของคุณ แต่โดยปกติจะไม่ จุดทั้งหมดของลักษณะคือการทำลายความคลุมเครือนั้น


คุณช่วยยกตัวอย่างภาษา / เทคโนโลยีให้ฉันเพื่อให้เป็น "อาคาร" ประเภทนั้นได้หรือไม่?
Gherman

@german - แน่นอนว่าฉันไม่มีผู้เชี่ยวชาญของสกาลา แต่ความเข้าใจของฉันคือสิ่งที่withคำหลักนั้นมี
Telastyn

"สร้างสิ่งที่จำกัดความสามารถของประเภทโดยเฉพาะเพื่อไม่ให้มีความกำกวม": ข้อ จำกัด ประเภทใด? อินเทอร์เฟซไม่มีตัวแปรดังนั้นมันจึงเป็นข้อ จำกัด อย่างหนึ่ง แต่คุณลักษณะของ Scala และโมดูล Ruby มีอยู่ พวกเขาถูก จำกัด ด้วยวิธีอื่น ๆ ?
David Moles

@DavidMoles - เป็นวิธีทั่วไปฉันได้เห็นข้อ จำกัด ของกฎการส่งข้อมูลเสมือน (คิดว่าส่วนต่อประสานที่ใช้งานของ C # ชัดเจน)
Telastyn
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.