คุณควรใช้อินเตอร์เฟส (ไม่ใช่การสืบทอด) หรือกลไกคุณสมบัติบางอย่าง (อาจเป็นบางสิ่งที่ทำงานได้เหมือนกรอบคำอธิบายทรัพยากร)
ดังนั้นทั้ง
interface Colored {
Color getColor();
}
class ColoredBook extends Book implements Colored {
...
}
หรือ
class PropertiesHolder {
<T> extends Property<?>> Optional<T> getProperty( Class<T> propertyClass ) { ... }
<V, T extends Property<V>> Optional<V> getPropertyValue( Class<T> propertyClass ) { ... }
}
interface Property<T> {
String getName();
T getValue();
}
class ColorProperty implements Property<Color> {
public Color getValue() { ... }
public String getName() { return "color"; }
}
class Book extends PropertiesHolder {
}
การชี้แจง (แก้ไข):
เพียงเพิ่มฟิลด์ตัวเลือกในคลาสเอนทิตี
โดยเฉพาะอย่างยิ่งกับ Wrapper ที่เป็นตัวเลือก (แก้ไข: ดูคำตอบของ4castle ) ฉันคิดว่านี่ (การเพิ่มเขตข้อมูลในเอนทิตีดั้งเดิม) เป็นวิธีที่ทำงานได้เพื่อเพิ่มคุณสมบัติใหม่ในขนาดเล็ก ปัญหาที่ใหญ่ที่สุดด้วยวิธีนี้คือมันอาจทำงานกับการมีเพศสัมพันธ์ต่ำ
ลองนึกภาพคลาสหนังสือของคุณถูกกำหนดไว้ในโครงการเฉพาะสำหรับแบบจำลองโดเมนของคุณ ตอนนี้คุณเพิ่มโครงการอื่นที่ใช้โมเดลโดเมนเพื่อทำงานพิเศษ ภารกิจนี้ต้องการคุณสมบัติเพิ่มเติมในคลาสหนังสือ ไม่ว่าคุณจะได้รับมรดก (ดูด้านล่าง) หรือคุณต้องเปลี่ยนรูปแบบโดเมนทั่วไปเพื่อให้งานใหม่เป็นไปได้ ในกรณีหลังคุณอาจจบลงด้วยโครงการมากมายที่ขึ้นอยู่กับคุณสมบัติของตัวเองที่เพิ่มเข้ากับชั้นหนังสือในขณะที่ชั้นเรียนของตัวเองขึ้นอยู่กับโครงการเหล่านี้เพราะคุณไม่สามารถเข้าใจชั้นหนังสือได้โดยไม่ต้อง โครงการเพิ่มเติม
เหตุใดการสืบทอดจึงเป็นปัญหาเมื่อหาวิธีให้คุณสมบัติเพิ่มเติม
เมื่อฉันเห็นชั้นเรียนของคุณ "หนังสือ" ฉันคิดถึงวัตถุในโดเมนที่มักจะจบลงด้วยการมีฟิลด์และตัวเลือกย่อยมากมาย แค่คิดว่าคุณต้องการเพิ่มอสังหาริมทรัพย์สำหรับหนังสือที่มีซีดี ขณะนี้มีหนังสือสี่ชนิด: หนังสือหนังสือที่มีสีหนังสือที่มีซีดีหนังสือที่มีสีและซีดี คุณไม่สามารถอธิบายสถานการณ์นี้ด้วยการสืบทอดใน Java
ด้วยส่วนต่อประสานที่คุณหลีกเลี่ยงปัญหานี้ คุณสามารถเขียนคุณสมบัติของคลาสหนังสือเฉพาะกับอินเทอร์เฟซได้อย่างง่ายดาย การมอบหมายและการจัดองค์ประกอบจะทำให้ง่ายต่อการได้รับชั้นที่คุณต้องการ ด้วยการสืบทอดคุณมักจะจบลงด้วยคุณสมบัติทางเลือกบางอย่างในคลาสที่มีเพียงเพราะคลาสพี่น้องต้องการพวกเขา
อ่านเพิ่มเติมว่าทำไมการสืบทอดมักเป็นแนวคิดที่มีปัญหา:
เหตุใดโดยทั่วไปการรับมรดกจึงมองว่าเป็นสิ่งเลวร้ายโดยผู้เสนอ OOP
JavaWorld: ทำไมการขยายความชั่วร้าย
ปัญหาเกี่ยวกับการนำชุดอินเตอร์เฟสไปใช้เพื่อสร้างชุดของคุณสมบัติ
เมื่อคุณใช้อินเทอร์เฟซสำหรับส่วนขยายทุกอย่างก็ใช้ได้ตราบใดที่คุณมีเพียงชุดเล็ก ๆ โดยเฉพาะอย่างยิ่งเมื่อโมเดลวัตถุของคุณถูกใช้และขยายโดยนักพัฒนาอื่น ๆ เช่นใน บริษัท ของคุณจำนวนของอินเทอร์เฟซจะเติบโต และในที่สุดคุณก็จบลงด้วยการสร้าง "อินเตอร์เฟซคุณสมบัติ" อย่างเป็นทางการใหม่ซึ่งเพิ่มวิธีการที่เพื่อนร่วมงานของคุณใช้ในโครงการของพวกเขาสำหรับลูกค้า X สำหรับกรณีการใช้งานที่ไม่เกี่ยวข้องอย่างสมบูรณ์ - ฮึ
แก้ไข: อีกด้านที่สำคัญคือการกล่าวถึงโดยgnasher729 คุณมักจะต้องการเพิ่มคุณสมบัติทางเลือกให้กับวัตถุที่มีอยู่แบบไดนามิก ด้วยการสืบทอดหรืออินเทอร์เฟซคุณจะต้องสร้างวัตถุทั้งหมดด้วยคลาสอื่นซึ่งอยู่ห่างจากทางเลือก
เมื่อคุณคาดว่าส่วนขยายของโมเดลวัตถุของคุณจะดีขึ้นโดยการสร้างแบบจำลองความเป็นไปได้ของส่วนขยายแบบไดนามิกอย่างชัดเจน ฉันเสนอสิ่งต่าง ๆ ข้างต้นโดยที่ "ส่วนขยาย" แต่ละรายการ (ในกรณีของคุณสมบัตินี้) มีคลาสของตัวเอง ชั้นทำงานเป็น namespace และตัวระบุสำหรับส่วนขยาย เมื่อคุณตั้งค่าอนุสัญญาการตั้งชื่อแพ็คเกจด้วยวิธีนี้จะอนุญาตให้มีการขยายจำนวนอนันต์โดยไม่ทำให้เกิดมลภาวะในเนมสเปซสำหรับวิธีการในคลาสเอนทิตีดั้งเดิม
ในการพัฒนาเกมคุณมักจะพบกับสถานการณ์ที่คุณต้องการเขียนพฤติกรรมและข้อมูลในหลายรูปแบบ นี่คือสาเหตุที่รูปแบบสถาปัตยกรรมเอนทิตีส่วนประกอบระบบได้รับความนิยมในแวดวงการพัฒนาเกม นี่เป็นวิธีที่น่าสนใจที่คุณอาจต้องการดูเมื่อคุณคาดหวังว่าส่วนขยายจำนวนมากสำหรับโมเดลวัตถุของคุณ