คำถามติดแท็ก inheritance

การสืบทอดเป็นวิธีการนำรหัสของวัตถุที่มีอยู่มาใช้ใหม่หรือเพื่อสร้างชนิดย่อยจากวัตถุที่มีอยู่หรือทั้งสองอย่างขึ้นอยู่กับการสนับสนุนภาษาโปรแกรม

4
มรดก vs mixins ในภาษาแบบไดนามิก?
เมื่อใดที่คุณควรเลือกรูปแบบการสืบทอดมากกว่ามิกซ์อินเป็นภาษาไดนามิก โดย mixins ฉันหมายถึงการผสมที่เหมาะสมตามจริงในขณะที่ใส่ฟังก์ชั่นและข้อมูลสมาชิกในวัตถุใน runtime ตัวอย่างเช่นเมื่อใดที่คุณจะใช้การถ่ายทอดทางพันธุกรรมต้นแบบแทนที่จะเป็นมิกซ์อิน เพื่อแสดงให้เห็นชัดเจนยิ่งขึ้นว่าฉันหมายถึงอะไรโดยมิกซ์อินบางรหัสเทียม: asCircle(obj) { obj.radius = 0 obj.area = function() { return this.radius * this.radius * 3.14 } myObject = {} asCircle(myObject) myObject.area() // -> 0

1
เหตุใดเบอร์ทรานด์เมเยอร์จึงคิดว่าการแบ่งคลาสย่อยเป็นวิธีเดียวที่จะขยายโมดูล“ ปิด”?
ในการสร้างซอฟต์แวร์เชิงวัตถุของเมเยอร์(1988) เขาได้กำหนดหลักการเปิด / ปิดดังต่อไปนี้: โมดูลจะได้รับการกล่าวถึงว่าเป็นเปิดถ้ามันยังคงมีอยู่สำหรับส่วนขยาย ตัวอย่างเช่นควรเป็นไปได้ที่จะเพิ่มเขตข้อมูลลงในโครงสร้างข้อมูลที่มีอยู่หรือองค์ประกอบใหม่ในชุดของฟังก์ชันที่ดำเนินการ โมดูลจะถูกปิดหากมีการใช้งานโดยโมดูลอื่น นี่ถือว่าโมดูลนั้นได้รับการกำหนดรายละเอียดที่ดีและมีเสถียรภาพ (อินเทอร์เฟซในแง่ของการซ่อนข้อมูล) เขาพูดต่อไปว่า: หากคุณเปิดโมดูลอีกครั้งคุณจะต้องเปิดไคลเอนต์ทั้งหมดอีกครั้งเพื่ออัปเดตโมดูลเนื่องจากใช้รุ่นเก่า … [ปัญหานี้] เกิดขึ้นทุกครั้งที่โมดูลจะต้องถูกขยายโดยฟังก์ชั่นใหม่หรือองค์ประกอบข้อมูลทำให้เกิดการเปลี่ยนแปลงในไคลเอนต์ทั้งทางตรงและทางอ้อม ... ด้วยวิธีการคลาสสิกในการออกแบบและการเขียนโปรแกรมจึงไม่มีวิธีเขียนโมดูลที่เปิดและปิด วิธีการแก้ปัญหาของเมเยอร์ในภาวะที่กลืนไม่เข้าคายไม่ออกนี้คือ: ไม่ขยายโมดูลห้องสมุดโดยการปรับเปลี่ยนคลาสที่มีอยู่; ให้เขียนโมดูลใหม่แทนคลาสย่อยที่มีอยู่แล้วและให้ไคลเอนต์ใหม่พึ่งพาโมดูลใหม่นั้น ตอนนี้ในปี 1988 ฉันเขียนโปรแกรมของเล่น (ขั้นตอน) ใน Turbo Pascal และ Blankenship Basic และประสบการณ์ระดับมืออาชีพในศตวรรษที่ 21 ของฉันคือ JVM, CLR และในภาษาไดนามิกดังนั้นฉันจึงไม่รู้ว่า Meyer แปลว่าอะไร โดย "แนวทางคลาสสิคเพื่อการออกแบบและการเขียนโปรแกรม" ตัวอย่างหนึ่งที่เป็นรูปธรรมของเมเยอร์ที่ว่าทำไมโมดูลลูกค้าจึงต้องเปิดใหม่ (คำสั่งเปลี่ยนจากการแจงนับซึ่งขณะนี้มีสมาชิกมากขึ้นต้องใช้เคสมากขึ้น) ดูสมเหตุสมผลพอสมควร แต่เขาไม่เกือบยืนยันว่าทุกครั้งที่คุณเพิ่มฟังก์ชันการทำงาน โมดูลคุณต้องอัปเดตไคลเอ็นต์ทั้งหมด มีเหตุผลทางประวัติศาสตร์ที่การยืนยันนี้ดูเหมือนชัดเจนในปี 1988? พูดหรือไม่ว่าการเพิ่มฟังก์ชั่นหรือโครงสร้างข้อมูลไปยัง C static library …

3
มีชื่อเฉพาะสำหรับบุคคลที่ผิดธรรมดา“ Square ที่สืบทอดมาจาก Rectangle” หรือไม่?
ความล้มเหลวบางอย่างของ OOP แสดงขึ้นพร้อมกับคลาส Square ที่สืบทอดมาจาก Rectangle โดยที่ Logical Square เป็นความเชี่ยวชาญเฉพาะของ Rectangle และควรสืบทอดมาจากมัน แต่ทุกอย่างจะแยกจากกันเมื่อคุณพยายามเปลี่ยนความยาวหรือความกว้างของ Square มีคำเฉพาะสำหรับการอธิบายสิ่งที่เกิดขึ้นกับกรณีนี้หรือไม่?

5
ควรใช้การสืบทอดเมื่อใดจึงจะใช้ 'เพียงฟิลด์บูลีน'
ในแอปพลิเคชัน Rails ของเราเรากำลังเพิ่มการแจ้งเตือน บางส่วนของสิ่งเหล่านี้คือblockingพวกเขาหยุดความคืบหน้าของทรัพยากรใด ๆ ที่พวกเขากำลังเพิ่มเพราะข้อมูลบางอย่างเกี่ยวกับทรัพยากรที่หายไป การแจ้งเตือนอื่น ๆ เป็นการแจ้งเตือนที่ง่ายและให้ข้อมูลเท่านั้น วันนี้ฉันได้พูดคุยกับโปรแกรมเมอร์คนอื่นในทีมของเรา ฉันได้สร้างโครงสร้างการสืบทอดเช่นนี้: อย่างไรก็ตามเขาต้องการให้ฉันเพิ่มblockingวิธีการส่งคืนบูลีนในแต่ละการแจ้งเตือนและระบุรายการของคลาสย่อยที่ปิดกั้นภายในคลาสพาเรนต์การแจ้งเตือน ความแตกต่างระหว่างวิธีการเหล่านี้ไม่มากนัก ในแนวทางของฉันไม่ต้องระบุรายการนี้ทำให้ root class cleaner ในทางตรงกันข้ามตรรกะพิเศษที่เกิดขึ้นในNotification::Blockingตอนนี้ก็ไม่ได้มีขนาดใหญ่มากเช่นกัน นามธรรมชนิดใดที่เหมาะกับปัญหานี้มากขึ้น?

4
เหตุใดจึงไม่มีตัวแก้ไขการเข้าถึง 'คลาสย่อยเท่านั้น' ใน Java
ใน Java มีตัวดัดแปลงการเข้าถึงที่ใช้ได้สี่วิธีสำหรับวิธีการ: public - คลาสใด ๆ สามารถใช้วิธีนี้ protected - คลาสในแพ็คเกจเดียวกันและคลาสย่อยในแพ็คเกจใด ๆ สามารถใช้วิธีนี้ได้ private - คลาสนี้เท่านั้นที่สามารถใช้วิธีนี้ no modifier ("แพ็คเกจส่วนตัว") - เฉพาะคลาสในแพ็คเกจเดียวกันเท่านั้นที่สามารถใช้วิธีนี้ได้ สิ่งที่เกิดขึ้นบ่อยครั้งคือฉันต้องการมีวิธีการที่มีประโยชน์ในซูเปอร์คลาสซึ่งคลาสย่อยทั้งหมดสามารถใช้ได้ แต่มันจะไม่สมเหตุสมผลสำหรับคลาสอื่น ๆ ในการเข้าถึงวิธีการนี้ ดังนั้นฉันจึงต้องประกาศวิธีการที่มีประโยชน์เหล่านี้ในซูเปอร์คลาสpublicหรือprotectedซึ่งเปิดเผยให้คลาสอื่น ๆ ทั้งหมดอย่างน้อยในแพ็คเกจ แม้ว่าคลาสย่อยเหล่านี้จะถูกใช้เพื่อการใช้งานเท่านั้น มีเหตุผลที่ไม่มีsubclasses-onlyตัวดัดแปลงการเข้าถึงใน Java หรือไม่? ดูเหมือนแปลกมากสำหรับฉัน ฉันพลาดอะไรไปรึเปล่า? นอกจากนี้subclasses-onlyตัวดัดแปลงการเข้าถึงจะมีประโยชน์เมื่อคุณต้องการเปิดเผยตัวแปรเฉพาะคลาสย่อย ซึ่งสำหรับฉันเกิดขึ้นมาก

4
เมื่อใดจึงจะย้ายเขตข้อมูลทั่วไปลงในคลาสพื้นฐานได้
ขณะนี้ฉันมีคลาสที่ได้รับสองคลาสAและBที่ทั้งสองมีเขตข้อมูลร่วมกันและฉันพยายามที่จะตรวจสอบว่ามันควรจะขึ้นไปในชั้นฐาน มันไม่เคยอ้างถึงจากชั้นฐานและบอกว่าในบางจุดลงมาที่ถนนอีกชั้นจะได้รับCที่ไม่ได้_field1แล้วจะไม่เป็นหลักของ "สิทธิพิเศษน้อย" (หรือบางสิ่งบางอย่าง) ถ้ามันถูกละเมิด เป็น? public abstract class Base { // Should _field1 be brought up to Base? //protected int Field1 { get; set; } } public class A : Base { private int _field1; } public class B : Base { private int _field1; } public class C …

14
ฉันจะอธิบายประโยชน์ของการสืบทอดได้อย่างไร [ปิด]
ตามที่เป็นอยู่ในปัจจุบันคำถามนี้ไม่เหมาะสำหรับรูปแบบคำถาม & คำตอบของเรา เราคาดหวังคำตอบที่จะได้รับการสนับสนุนจากข้อเท็จจริงการอ้างอิงหรือความเชี่ยวชาญ แต่คำถามนี้อาจเรียกร้องให้มีการถกเถียงโต้แย้งโต้แย้งหรือการอภิปรายเพิ่มเติม หากคุณรู้สึกว่าคำถามนี้สามารถปรับปรุงและเปิดใหม่ได้โปรดไปที่ศูนย์ช่วยเหลือเพื่อขอคำแนะนำ ปิดให้บริการใน6 ปีที่ผ่านมา เมื่อพยายามอธิบายแนวคิดของการสืบทอดใน OOP ตัวอย่างทั่วไปมักเป็นตัวอย่างสัตว์เลี้ยงลูกด้วยนม IMHO นี่เป็นตัวอย่างที่ไม่ดีจริงๆเพราะมันจะทำให้มือใหม่ใช้แนวคิดนี้ในทางที่ผิด และยิ่งไปกว่านั้นมันไม่ใช่การออกแบบทั่วไปที่พวกเขาจะต้องเผชิญในงานออกแบบประจำวัน ดังนั้นสิ่งที่จะเป็นปัญหาที่ดีเรียบง่ายและเป็นรูปธรรมที่แก้ไขได้โดยใช้มรดก?

1
วิธีการตรวจสอบหลักการทดแทน Liskov ในลำดับชั้นการสืบทอด?
แรงบันดาลใจจากคำตอบนี้ : หลักการทดแทน Liskov ต้องการ สิ่งนั้น เงื่อนไขเบื้องต้นไม่สามารถเสริมความแข็งแกร่งในประเภทย่อย Postconditions ไม่สามารถลดลงในประเภทย่อย ค่าคงที่ของซูเปอร์ไทป์จะต้องเก็บรักษาไว้ในประเภทย่อย ข้อ จำกัด ประวัติ ("กฎประวัติศาสตร์") วัตถุนั้นได้รับการยกย่องว่าสามารถปรับเปลี่ยนได้ด้วยวิธีการของพวกเขาเท่านั้น (encapsulation) เนื่องจากชนิดย่อยอาจแนะนำวิธีการที่ไม่ปรากฏใน supertype การแนะนำวิธีการเหล่านี้อาจอนุญาตให้มีการเปลี่ยนแปลงสถานะในชนิดย่อยที่ไม่อนุญาตใน supertype ข้อ จำกัด ประวัติห้ามสิ่งนี้ ฉันหวังว่าถ้ามีคนจะโพสต์ลำดับชั้นของชั้นเรียนที่ละเมิด 4 คะแนนและจะแก้ไขได้อย่างไร ฉันกำลังมองหาคำอธิบายอย่างละเอียดเพื่อจุดประสงค์ด้านการศึกษาเกี่ยวกับวิธีระบุแต่ละจุดในลำดับชั้นและวิธีที่ดีที่สุดในการแก้ไข หมายเหตุ: ฉันหวังว่าจะโพสต์ตัวอย่างโค้ดเพื่อให้คนทำงาน แต่คำถามนั้นเกี่ยวกับวิธีระบุลำดับชั้นผิดพลาด :)

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

8
“ ชอบการแต่งเพลงมากกว่ามรดก” - เป็นเหตุผลเดียวที่จะป้องกันการเปลี่ยนแปลงลายเซ็นได้หรือไม่?
หน้านี้สนับสนุนการแต่งเพลงมากกว่าการสืบทอดด้วยอาร์กิวเมนต์ต่อไปนี้ (ใช้ถ้อยคำใหม่ในคำพูดของฉัน): การเปลี่ยนแปลงในลายเซ็นของวิธีการของซูเปอร์คลาส (ซึ่งไม่ได้ถูกแทนที่ในคลาสย่อย) ทำให้เกิดการเปลี่ยนแปลงเพิ่มเติมในหลาย ๆ สถานที่เมื่อเราใช้การสืบทอด อย่างไรก็ตามเมื่อเราใช้ Composition การเปลี่ยนแปลงเพิ่มเติมที่จำเป็นนั้นมีอยู่ในที่เดียวนั่นคือคลาสย่อย นั่นเป็นเหตุผลเดียวที่จะสนับสนุนการแต่งเพลงมากกว่าการสืบทอด? เพราะถ้าเป็นกรณีนี้ปัญหานี้สามารถบรรเทาได้ง่ายโดยบังคับใช้รูปแบบการเข้ารหัสที่สนับสนุนการเอาชนะวิธีการทั้งหมดของ superclass แม้ว่า subclass จะไม่เปลี่ยนการใช้งาน (นั่นคือการใส่ dummy แทนที่ใน subclass) ฉันทำอะไรบางอย่างหายไปหรือเปล่า

2
ฉันจะหลีกเลี่ยงการเขียนฟังก์ชัน pass-through มากมายใน wrapper ได้อย่างไร
ฉันมีคลาสซึ่งล้อมคลาสอื่นที่เป็นประเภทพื้นฐานทั่วไป เนื่องจากอินเตอร์เฟสประเภทฐานมีขนาดค่อนข้างใหญ่จึงเกี่ยวข้องกับการเขียนฟังก์ชั่นการส่งผ่านจำนวนมาก ฉันกำลังมองหาวิธีที่จะหลีกเลี่ยงปัญหานี้ ลองทำตัวอย่าง: Car / \ Volvo VolvoWithTrailer ตอนนี้ฉันต้องติดตั้งฟังก์ชั่นแต่ละอย่างในอินเทอร์เฟซสำหรับรถยนต์ของ VolvoWithTrailer และเรียกใช้ฟังก์ชั่นที่เหมาะสมบนวัตถุที่ห่อหุ้มวอลโว่ยกเว้นอาจ GetMaxSpeed ​​() ซึ่งจะคืนสิ่งที่ต่ำกว่า โดยทั่วไปฉันจะมีฟังก์ชั่นมากมายเช่น int VolvoWithTrailer::GetNumSeats() { return mVolvo.GetNumSeats() } วิธีที่ชัดเจนในการแก้ไขปัญหานี้คือการทำให้ VolvoWithTrailer เป็น subclass ของ Volvo Car | Volvo | VolvoWithTrailer แต่ดูเหมือนว่าจะละเมิดหลักการของการสนับสนุนการแต่งมากกว่ามรดก ฉันจะหลีกเลี่ยงการเขียนโปรแกรมเสริมเหล่านี้ได้อย่างไร (ภาษาคือ C ++) หรือ - ถ้านั่นคือตำแหน่งของคุณ - ทำไมฉันต้องเขียนพวกเขา / แค่ใช้การสืบทอด? มีแม่แบบเวทย์มนตร์ที่สามารถช่วยได้หรือไม่?

3
องค์ประกอบมากกว่ามรดก แต่
ฉันพยายามสอนตัวเองเกี่ยวกับวิศวกรรมซอฟต์แวร์และการหาข้อมูลที่ขัดแย้งกันซึ่งทำให้ฉันสับสน ฉันได้เรียนรู้เกี่ยวกับ OOP และคลาสนามธรรม / อินเทอร์เฟซคืออะไรและใช้งานอย่างไร แต่จากนั้นฉันก็อ่านว่าควรจะ 'สนับสนุนองค์ประกอบเหนือมรดก' ฉันเข้าใจการจัดองค์ประกอบคือเมื่อคลาสหนึ่งประกอบ / สร้างวัตถุของคลาสอื่นเพื่อใช้ / โต้ตอบกับฟังก์ชันการทำงานของวัตถุใหม่นั้น ดังนั้นคำถามของฉันคือ ... ฉันควรจะไม่ใช้คลาสหรืออินเตอร์เฟสแบบนามธรรมหรือไม่? หากไม่ต้องการสร้างคลาสนามธรรมและขยาย / สืบทอดฟังก์ชันการทำงานของคลาสนามธรรมในคลาสที่เป็นรูปธรรมและแทนที่จะสร้างวัตถุใหม่เพื่อใช้ฟังก์ชันของคลาสอื่น หรือฉันควรใช้องค์ประกอบและสืบทอดจากคลาสนามธรรม; ใช้พวกเขาทั้งสองร่วมกัน? ถ้าเป็นเช่นนั้นคุณช่วยยกตัวอย่างว่ามันจะทำงานอย่างไรและมีประโยชน์อย่างไร เนื่องจากฉันคุ้นเคยกับ PHP มากที่สุดฉันจึงใช้มันเพื่อพัฒนาทักษะ OOP / SE ของฉันก่อนที่จะย้ายไปใช้ภาษาอื่นและถ่ายโอนทักษะ SE ที่เพิ่งได้รับมาดังนั้นตัวอย่างการใช้ PHP จะได้รับการชื่นชมมากที่สุด

2
เหตุใดคลาสพื้นฐานจำเป็นต้องมี destructor เสมือนจริงที่นี่ถ้าคลาสที่ได้รับจัดสรรหน่วยความจำแบบไดนามิกดิบไม่ได้?
รหัสต่อไปนี้ทำให้หน่วยความจำรั่ว: #include <iostream> #include <memory> #include <vector> using namespace std; class base { void virtual initialize_vector() = 0; }; class derived : public base { private: vector<int> vec; public: derived() { initialize_vector(); } void initialize_vector() { for (int i = 0; i < 1000000; i++) { vec.push_back(i); } } }; …

5
การสืบทอด vs คุณสมบัติเพิ่มเติมที่มีค่า Null
สำหรับคลาสที่มีฟิลด์เป็นตัวเลือกจะดีกว่าถ้าใช้การสืบทอดหรือคุณสมบัติที่เป็นโมฆะ? ลองพิจารณาตัวอย่างนี้: class Book { private String name; } class BookWithColor extends Book { private String color; } หรือ class Book { private String name; private String color; //when this is null then it is "Book" otherwise "BookWithColor" } หรือ class Book { private String name; private Optional<String> color; //when …
12 java  inheritance  class  null 

3
อินเทอร์เฟซจะถือว่าว่างหรือไม่ถ้ามันสืบทอดมาจากอินเทอร์เฟซอื่นหรือไม่
อินเทอร์เฟซที่ว่างเปล่าโดยทั่วไปจะพิจารณาการปฏิบัติที่ไม่ดีเท่าที่ฉันสามารถบอกได้ - โดยเฉพาะอย่างยิ่งเมื่อสิ่งต่าง ๆ เช่นแอตทริบิวต์ได้รับการสนับสนุนโดยภาษา อย่างไรก็ตามอินเทอร์เฟซถูกพิจารณาว่า 'ว่าง' ถ้ามันได้รับมาจากอินเทอร์เฟซอื่นหรือไม่ interface I1 { ... } interface I2 { ... } //unrelated to I1 interface I3 : I1, I2 { // empty body } สิ่งใดที่ใช้I3จะต้องนำไปปฏิบัติI1และI2และวัตถุจากคลาสที่แตกต่างกันซึ่งสืบทอดI3สามารถนำมาใช้แทนกันได้ (ดูด้านล่าง) ดังนั้นมันถูกต้องหรือI3 เปล่าที่จะเรียกว่าว่างเปล่า ? ถ้าเป็นเช่นนั้นจะมีวิธีใดที่ดีกว่าในการสร้างสถาปัตยกรรมนี้ // with I3 interface class A : I3 { ... } class B …

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