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

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

9
การออกแบบสำหรับการสืบทอดสามารถทำให้มีค่าใช้จ่ายเพิ่มเติมได้อย่างไร [ปิด]
ปิด คำถามนี้เป็นคำถามความคิดเห็นตาม ไม่ยอมรับคำตอบในขณะนี้ ต้องการปรับปรุงคำถามนี้หรือไม่ อัปเดตคำถามเพื่อให้สามารถตอบข้อเท็จจริงและการอ้างอิงได้โดยแก้ไขโพสต์นี้ ปิดให้บริการใน6 ปีที่ผ่านมา ดังนั้นฉันต้องการสืบทอดจากsealed classในcsharpและถูกไฟไหม้ ไม่มีทางที่จะเปิดผนึกจนกว่าคุณจะเข้าถึงแหล่งข้อมูลได้ ฉันคิดว่า "ทำไมsealedถึงมีอยู่จริง" 4 เดือนที่แล้ว ฉันไม่สามารถเข้าใจได้แม้จะอ่านสิ่งต่าง ๆ มากมายเช่น: ความปรารถนาของ Jon Skeet " คลาสถูกปิดผนึกโดยค่าเริ่มต้นใน. NET " ชอบการแต่งมากกว่าการสืบทอด? "คุณไม่ควรปิดคลาสทั้งหมด (... )" คุณจะล้อเลียนคลาสที่ปิดสนิทได้อย่างไร ฉันพยายามย่อยทุกอย่างตั้งแต่นั้นมา แต่มันก็มากเกินไปสำหรับฉัน ในที่สุดเมื่อวานฉันลองอีกครั้ง ฉันสแกนพวกเขาทั้งหมดอีกครั้งและอีกไม่กี่: ทำไมชั้นเรียนควรเป็นอย่างอื่นนอกจาก "นามธรรม" หรือ "ขั้นสุดท้าย / ปิดผนึก" ในการเขียนโปรแกรมกว่า 15 ปีครั้งแรกที่ฉันได้ยินเกี่ยวกับSOLIDจากคำตอบของคำถามที่เชื่อมโยงแล้วและเห็นได้ชัดว่าฉันไม่ได้อ่านมาตลอด 4 เดือนที่ผ่านมา ในที่สุดหลังจากการไตร่ตรองมากมายฉันตัดสินใจที่จะแก้ไขคำถามเดิมอย่างหนักตามชื่อเรื่องใหม่ คำถามเดิมกว้างเกินไปและอัตนัย มันเป็นพื้นถาม: ในชื่อเก่า: เหตุผลหนึ่งที่ดีในการใช้ตราประทับ ในร่างกาย: …
12 c#  inheritance 

2
ทำไม Java ไม่สนับสนุนการสืบทอดส่วนตัว / ที่ป้องกันเช่น C ++ [ปิด]
ตามที่เป็นอยู่ในปัจจุบันคำถามนี้ไม่เหมาะสำหรับรูปแบบคำถาม & คำตอบของเรา เราคาดหวังคำตอบที่จะได้รับการสนับสนุนจากข้อเท็จจริงการอ้างอิงหรือความเชี่ยวชาญ แต่คำถามนี้มีแนวโน้มที่จะเรียกร้องให้มีการอภิปรายโต้แย้งโต้แย้งหรือการอภิปรายเพิ่มเติม หากคุณรู้สึกว่าคำถามนี้สามารถปรับปรุงและเปิดใหม่ได้โปรดไปที่ศูนย์ช่วยเหลือเพื่อขอคำแนะนำ ปิดให้บริการใน7 ปีที่ผ่านมา ในขณะที่สืบทอดคลาสใน C ++ ผู้ใช้สามารถระบุตัวระบุการเข้าถึงเช่น class Base { public int mem1; protected in mem2; }; class Derived1 : **private** Base { // mem1 will be private here. // mem2 will be private here. }; class Derived2 : **protected** Base { // mem1 will …

4
ลำดับชั้นแบบขนาน - เหมือนกันบางส่วนแตกต่างกันเล็กน้อย
มีคำถามที่คล้ายกันอยู่สองสามข้อ 1 ,2 ,3 ,4แต่ดูเหมือนว่าไม่ใช่ในกรณีของคำถามนี้และการแก้ปัญหาก็ดูดีที่สุด นี่เป็นคำถามทั่วไปของ OOP โดยสมมติว่ามีหลายรูปแบบชื่อสามัญและมิกซ์อินมีอยู่ ภาษาจริงที่ใช้คือ OOP Javascript (Typescript) แต่เป็นปัญหาเดียวกันใน Java หรือ C ++ ฉันมีลำดับชั้นของชั้นเรียนแบบขนานซึ่งบางครั้งก็มีพฤติกรรมที่เหมือนกัน (ส่วนต่อประสานและการใช้งาน) แต่บางครั้งก็มีพฤติกรรมที่ 'ได้รับการป้องกัน' ของตัวเอง ภาพประกอบดังนี้: นี้สำหรับวัตถุประสงค์ในการประกอบการอธิบายเท่านั้น ; มันไม่ใช่แผนภาพคลาสที่แท้จริง หากต้องการอ่าน: สิ่งใดก็ตามในลำดับชั้นทั่วไป (กลาง) จะแชร์กันระหว่างทั้ง Canvas (ซ้าย) และ SVG (ขวา) ด้วยการแบ่งปันฉันหมายถึงทั้งอินเทอร์เฟซและการใช้งาน สิ่งใดก็ตามที่อยู่บนคอลัมน์ซ้ายหรือขวาหมายถึงพฤติกรรม (วิธีการและสมาชิก) เฉพาะสำหรับลำดับชั้นนั้น ตัวอย่างเช่น: ทั้งลำดับชั้นซ้ายและขวาใช้กลไกการตรวจสอบความถูกต้องเดียวกันแสดงเป็นวิธีการเดียว ( Viewee.validate()) ในลำดับชั้นทั่วไป paint()เพียงลำดับชั้นของผ้าใบมีวิธีการ วิธีนี้เรียกวิธีการทาสีบนเด็กทุกคน ลำดับชั้น SVG จำเป็นต้องแทนที่addChild()วิธีการCompositeแต่ไม่ได้เป็นกรณีที่มีลำดับชั้นของผืนผ้าใบ โครงสร้างจากลำดับชั้นทั้งสองไม่สามารถผสมกันได้ …

5
ฉันควรจะชอบองค์ประกอบหรือการสืบทอดในสถานการณ์นี้หรือไม่
พิจารณาอินเทอร์เฟซ: interface IWaveGenerator { SoundWave GenerateWave(double frequency, double lengthInSeconds); } อินเทอร์เฟซนี้ถูกใช้งานโดยคลาสที่สร้างคลื่นของรูปร่างที่แตกต่างกัน (ตัวอย่างเช่นSineWaveGeneratorและSquareWaveGenerator) ฉันต้องการใช้คลาสที่สร้างSoundWaveจากข้อมูลดนตรีไม่ใช่ข้อมูลเสียงดิบ มันจะได้รับชื่อของโน้ตและระยะเวลาในแง่ของการเต้น (ไม่กี่วินาที) ที่และภายในใช้IWaveGeneratorฟังก์ชั่นในการสร้างSoundWaveตาม คำถามคือควรNoteGeneratorประกอบด้วยIWaveGeneratorหรือควรได้รับมรดกจากการIWaveGeneratorดำเนินการ? ฉันเอนตัวไปยังองค์ประกอบเนื่องจากเหตุผลสองประการ: 1- มันช่วยให้ฉันสามารถฉีดใด ๆIWaveGeneratorไปยังNoteGeneratorแบบไดนามิก นอกจากนี้ฉันต้องการเพียงหนึ่งNoteGeneratorชั้นแทนSineNoteGenerator, SquareNoteGeneratorฯลฯ 2- มีความต้องการไม่ได้ที่จะเปิดเผยอินเตอร์เฟซในระดับต่ำกว่าที่กำหนดโดยNoteGeneratorIWaveGenerator อย่างไรก็ตามฉันโพสต์คำถามนี้เพื่อฟังความคิดเห็นอื่น ๆ เกี่ยวกับเรื่องนี้อาจเป็นจุดที่ฉันไม่ได้คิด BTW: ฉันจะบอกว่าNoteGenerator เป็นแนวคิดIWaveGeneratorเพราะมันสร้างSoundWaves

5
อินเตอร์เฟซแยกต่างหากสำหรับวิธีการกลายพันธุ์
ฉันทำงานเกี่ยวกับการรีแฟคเตอร์โค้ดบางส่วนและฉันคิดว่าฉันอาจทำขั้นตอนแรกลงไปในช่องกระต่าย ฉันเขียนตัวอย่างใน Java แต่ฉันคิดว่ามันอาจเป็นผู้ไม่เชื่อเรื่องพระเจ้า ฉันมีอินเตอร์เฟซที่Fooกำหนดเป็น public interface Foo { int getX(); int getY(); int getZ(); } และการดำเนินการตาม public final class DefaultFoo implements Foo { public DefaultFoo(int x, int y, int z) { this.x = x; this.y = y; this.z = z; } public int getX() { return x; } public …

9
การออกแบบ OO ใดที่จะใช้ (มีรูปแบบการออกแบบ)
ฉันมีวัตถุสองชิ้นที่แสดงถึง 'บาร์ / คลับ' (สถานที่ที่คุณดื่ม / สังสรรค์) ในสถานการณ์หนึ่งฉันต้องการชื่อบาร์ที่อยู่ระยะทางสโลแกน ในสถานการณ์อื่นฉันต้องการชื่อบาร์, ที่อยู่, URL เว็บไซต์, โลโก้ ดังนั้นฉันจึงมีวัตถุสองชิ้นที่เป็นตัวแทนของสิ่งเดียวกัน แต่มีเขตข้อมูลที่แตกต่างกัน ผมชอบที่จะใช้วัตถุที่ไม่เปลี่ยนรูปเพื่อให้ทุกสาขามีการตั้งค่าจากตัวสร้าง ตัวเลือกหนึ่งคือการมีสองคอนสตรัคเตอร์และโมฆะสาขาอื่น ๆ เช่น: class Bar { private final String name; private final Distance distance; private final Url url; public Bar(String name, Distance distance){ this.name = name; this.distance = distance; this.url = null; } public …

5
วิธีการใช้มรดก RealNumber และ ComplexNumber
หวังว่าจะไม่เป็นนักวิชาการ ... สมมติว่าฉันต้องการจำนวนจริงและซับซ้อนในห้องสมุด SW ของฉัน ขึ้นอยู่กับความสัมพันธ์แบบis-a (หรือที่นี่ ) จำนวนจริงเป็นจำนวนเชิงซ้อนโดย b ในส่วนจินตภาพของจำนวนเชิงซ้อนเป็นเพียง 0 ในทางตรงกันข้ามการดำเนินการของฉันจะเป็นเด็กที่ขยายผู้ปกครองดังนั้นในผู้ปกครอง RealNumber ฉันมีส่วนจริงและเด็ก ComplexNumber จะเพิ่มงานศิลปะจินตภาพ นอกจากนี้ยังมีความเห็นว่าการรับมรดกเป็นความชั่วร้าย ฉันจำได้เหมือนเมื่อวานเมื่อฉันเรียนรู้ OOP ที่มหาวิทยาลัยอาจารย์ของฉันบอกว่านี่ไม่ใช่ตัวอย่างที่ดีของการสืบทอดเนื่องจากค่าสัมบูรณ์ของทั้งสองนั้นคำนวณต่างกัน (แต่สำหรับวิธีที่เรามีวิธีการมากไป . ประสบการณ์ของฉันคือเรามักจะใช้การสืบทอดเพื่อแก้ปัญหา DRY ดังนั้นเรามักจะมีคลาสนามธรรมที่เป็นนามธรรมในลำดับชั้น (เรามักจะมีปัญหาในการค้นหาชื่อเพราะพวกเขาไม่ได้เป็นตัวแทนวัตถุจากโลกแห่งความเป็นจริง)

5
การละเมิด LSP เคยถูกหรือไม่?
ฉันกำลังติดตามคำถามนี้แต่ฉันเปลี่ยนโฟกัสจากโค้ดเป็นหลักการ จากความเข้าใจของฉันเกี่ยวกับหลักการทดแทน Liskov (LSP) ไม่ว่าวิธีการใดที่อยู่ในคลาสพื้นฐานของฉันพวกเขาจะต้องดำเนินการในคลาสย่อยของฉันและตามหน้านี้หากคุณแทนที่วิธีในคลาสพื้นฐานและไม่ทำอะไรเลย คุณกำลังละเมิดหลักการ ตอนนี้ปัญหาของฉันสามารถสรุปได้เช่นนี้ฉันมีนามธรรมWeapon classและสองชั้นและSword ReloadableหากReloadableมีข้อมูลเฉพาะที่methodเรียกว่าReload()ฉันจะต้องลดความเร็วเพื่อเข้าถึงmethodและถ้าคุณต้องการหลีกเลี่ยงปัญหานั้น Strategy Patternจากนั้นผมก็คิดของการใช้ วิธีนี้แต่ละอาวุธเป็นเพียงตระหนักถึงการกระทำที่มีความสามารถในการดำเนินการดังนั้นสำหรับตัวอย่างเช่นReloadableอาวุธอย่างเห็นได้ชัดสามารถโหลด แต่ไม่สามารถและไม่ได้ตระหนักถึงSword Reload class/methodตามที่ระบุไว้ในโพสต์ Stack Overflow ของฉันฉันไม่จำเป็นต้องลดความเร็วและฉันสามารถเก็บList<Weapon>สะสม ในฟอรัมอื่นคำตอบแรกที่แนะนำเพื่อให้SwordระวังReloadเพียงไม่ทำอะไรเลย ได้รับคำตอบเดียวกันนี้ในหน้า Stack Overflow ที่ฉันลิงค์ไปด้านบน ฉันไม่เข้าใจว่าทำไม ทำไมการละเมิดหลักการและอนุญาตให้ Sword ต้องระวังReloadและปล่อยให้มันว่างเปล่า อย่างที่ฉันบอกไว้ในโพสต์ Stack Overflow SP จะแก้ปัญหาของฉันได้ค่อนข้างมาก ทำไมมันไม่เป็นทางออกที่ทำงานได้? public final Weapon{ private final String name; private final int damage; private final List<AttackStrategy> validactions; private final …

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

2
การสืบทอดของ Python เป็นรูปแบบของ "is-a" ของการสืบทอดหรือสไตล์การแต่งหรือไม่?
เนื่องจาก Python อนุญาตให้ใช้การสืบทอดหลายแบบการถ่ายทอดทางพันธุกรรมใน Python มีลักษณะอย่างไร ในภาษาที่มีการสืบทอดเดียวเช่น Java การสืบทอดจะถูกใช้เมื่อคุณสามารถพูดได้ว่าวัตถุหนึ่ง "is-a" ของวัตถุอื่นและคุณต้องการแบ่งปันรหัสระหว่างวัตถุ (จากวัตถุหลักไปยังวัตถุลูก) ตัวอย่างเช่นคุณสามารถพูดได้ว่าDogเป็นAnimal: public class Animal {...} public class Dog extends Animal {...} แต่เนื่องจาก Python รองรับการสืบทอดหลายแบบเราจึงสามารถสร้างวัตถุโดยการรวมวัตถุอื่นเข้าด้วยกัน ลองพิจารณาตัวอย่างด้านล่าง: class UserService(object): def validate_credentials(self, username, password): # validate the user credentials are correct pass class LoggingService(object): def log_error(self, error): # log an error pass …

3
การสืบทอด: เป็นรหัสจาก superclass จริง * คัดลอก * ไปยังคลาสย่อยหรือเป็น * อ้างถึงโดย subclass *?
ชั้นSubเป็น subclass Supของชั้นเรียน นั่นหมายความว่าในทางปฏิบัติจริง ๆ ? หรือกล่าวอีกนัยหนึ่งความหมายในทางปฏิบัติของ "การสืบทอด" คืออะไร? ตัวเลือกที่ 1:รหัสจาก Sup จะถูกคัดลอกไปยัง Sub อย่างแท้จริง (เหมือนใน 'copy-paste' แต่ไม่มีโค้ดที่คัดลอกที่มองเห็นได้ในคลาสย่อย) ตัวอย่าง: methodA()เป็นวิธีการดั้งเดิมใน Sup Sub ขยาย Sup ดังนั้นจึงmethodA()เป็น (แทบ) คัดลอกวางไปที่ Sub methodA()ตอนนี้ตมีวิธีการตั้งชื่อ มันเหมือนกับของ Sup methodA()ในทุกบรรทัดของโค้ด แต่เป็นของ Sub - ทั้งหมดและไม่ขึ้นกับ Sup หรือเกี่ยวข้องกับ Sup ในทางใดทางหนึ่ง ตัวเลือกที่ 2:รหัสจาก Sup ไม่ได้ถูกคัดลอกไปยัง Sub จริง ๆ มันยังคงอยู่ในซูเปอร์คลาสเท่านั้น แต่โค้ดนั้นสามารถเข้าถึงได้ผ่านคลาสย่อยและสามารถใช้งานได้โดยคลาสย่อย ตัวอย่าง: …

12
“ ถ้าวิธีการถูกนำมาใช้ใหม่โดยไม่มีการเปลี่ยนแปลงให้ใส่วิธีการในคลาสพื้นฐานมิฉะนั้นสร้างอินเทอร์เฟซ” เป็นกฎที่ดี?
เพื่อนร่วมงานของฉันเกิดขึ้นกับกฎง่ายๆสำหรับการเลือกระหว่างการสร้างชั้นฐานหรืออินเตอร์เฟซ เขาพูดว่า: ลองนึกภาพทุกวิธีการใหม่ที่คุณกำลังจะใช้ สำหรับแต่ละของพวกเขาพิจารณานี้จะใช้วิธีการนี้จะดำเนินการโดยระดับมากกว่าหนึ่งในว่ารูปแบบนี้โดยไม่ต้องใด ๆการเปลี่ยนแปลง? หากคำตอบคือ "ใช่" ให้สร้างคลาสพื้นฐาน ในทุกสถานการณ์ให้สร้างอินเทอร์เฟซ ตัวอย่างเช่น: พิจารณาการเรียนcatและdogซึ่งขยายชั้นเรียนและมีวิธีการเดียวmammal pet()จากนั้นเราจะเพิ่มชั้นเรียนซึ่งไม่ขยายอะไรและมีวิธีการเดียวalligatorslither() ตอนนี้เราต้องการเพิ่มeat()วิธีการทั้งหมดของพวกเขา หากการดำเนินการตามeat()วิธีการที่จะตรงเดียวกันcat, dogและalligatorเราควรสร้างชั้นฐาน (สมมุติว่าanimal) ซึ่งใช้วิธีการนี้ อย่างไรก็ตามหากการติดตั้งใช้งานalligatorแตกต่างกันเล็กน้อยเราควรสร้างIEatส่วนต่อประสานและสร้างmammalและalligatorนำไปใช้งาน เขายืนยันว่าวิธีนี้ครอบคลุมทุกกรณี แต่ดูเหมือนว่าฉันจะทำให้เข้าใจง่ายเกินไป การทำตามกฎของหัวแม่มือนี้มีค่าหรือไม่

2
ทำไมการใช้คอนสตรัคเตอร์ท้อใจเมื่อสร้างต้นแบบ?
พื้นหลังด่วน:ใน JavaScript ฟังก์ชันตัวสร้างสำหรับวัตถุแต่ละชนิดมีprototypeคุณสมบัติ การprototypeอ้างถึงวัตถุที่แต่ละวัตถุที่สร้างขึ้นใช้เป็นขั้นตอนต่อไปในห่วงโซ่ต้นแบบ เมื่อคุณต้องการให้มีประเภทหนึ่งโดยธรรมชาติจากประเภทอื่นคุณสามารถตั้งค่าprototypeประเภทเด็กเป็นอินสแตนซ์ใหม่ของประเภทแม่ ตัวอย่างเช่น: var Parent = function() { /* constructor business */ } Parent.prototype.parentProp = "some parent property"; var Child = function() { /* constructor business */ } Child.prototype = /*** !! Some prototype object goes here !! ***/ คำถามของฉันถามเกี่ยวกับรหัสที่ควรไปในSome prototype object goes hereจุดที่ระบุในรหัสด้านบน สัญชาตญาณแรกของฉันคือสร้างอินสแตนซ์ของพาเรนต์ (เช่นnew Parent()) …

6
ทำไมการทำคลาสย่อยแย่เกินไป (และด้วยเหตุนี้เราควรใช้ต้นแบบเพื่อทำไป)
ฉันอ่านเกี่ยวกับรูปแบบการออกแบบและฉันอ่านว่ารูปแบบการออกแบบต้นแบบนั้นมีซับคลาสที่มากเกินไป ทำไมการแบ่งคลาสย่อยไม่ดี การใช้ต้นแบบจะได้ประโยชน์อะไรจากการทำ subclassing

5
อินเทอร์เฟซและการสืบทอด: สุดยอดของทั้งสองโลก
ฉันค้นพบอินเทอร์เฟซและฉันเริ่มรักพวกเขา ความสวยงามของอินเทอร์เฟซคือมันเป็นสัญญาและวัตถุใด ๆ ที่ตอบสนองสัญญานั้นสามารถใช้ได้ทุกที่ที่ต้องการอินเตอร์เฟส ปัญหาของอินเทอร์เฟซคือมันไม่สามารถมีการใช้งานเริ่มต้นซึ่งเป็นคุณสมบัติที่เจ็บปวดสำหรับคุณสมบัติทางโลกและกำจัด DRY สิ่งนี้ก็เป็นสิ่งที่ดีเพราะมันทำให้การใช้งานและระบบแยกจากกัน ในทางกลับกันมรดกยังคงรักษาคัปปลิ้งที่แน่นกว่าและมีศักยภาพที่จะทำลายการห่อหุ้ม กรณีที่ 1 (การสืบทอดกับสมาชิกส่วนตัวการห่อหุ้มที่ดีเข้าด้วยกันอย่างแน่นหนา) class Employee { int money_earned; string name; public: void do_work(){money_earned++;}; string get_name(return name;); }; class Nurse : public Employee: { public: void do_work(/*do work. Oops, can't update money_earned. Unaware I have to call superclass' do_work()*/); }; void HireNurse(Nurse *n) …

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