मैं इस प्रश्न का अनुसरण कर रहा हूं , लेकिन मैं अपना ध्यान कोड से एक सिद्धांत पर स्विच कर रहा हूं।
लिस्कोव प्रतिस्थापन सिद्धांत (एलएसपी) की मेरी समझ से , मेरे आधार वर्ग में जो भी तरीके हैं, उन्हें मेरे उपवर्ग में लागू किया जाना चाहिए, और इस पृष्ठ के अनुसार , यदि आप आधार वर्ग में एक विधि को ओवरराइड करते हैं और यह कुछ भी नहीं करता है या फेंकता है अपवाद, आप सिद्धांत के उल्लंघन में हैं।
अब, मेरी समस्या को इस तरह से अभिव्यक्त किया जा सकता है: मेरे पास एक सार है Weapon
class
, और दो वर्ग हैं, Sword
और Reloadable
। यदि Reloadable
कोई विशिष्ट method
, बुलाया जाता है Reload()
, तो मुझे उस तक पहुंचने के लिए डाउनकास्ट करना होगा method
, और, आदर्श रूप से, आप इससे बचना चाहेंगे।
मैं तो का उपयोग करने के बारे में सोचा Strategy Pattern
। इस तरह से प्रत्येक हथियार केवल उन कार्यों के बारे में पता था जो यह प्रदर्शन करने में सक्षम है, इसलिए, उदाहरण के लिए, एक Reloadable
हथियार, स्पष्ट रूप से पुनः लोड हो सकता है, लेकिन एक Sword
भी नहीं हो सकता है और एक के बारे में भी पता नहीं है Reload class/method
। जैसा कि मैंने अपने स्टैक ओवरफ्लो पोस्ट में कहा था, मुझे डाउनकास्ट नहीं करना है, और मैं एक List<Weapon>
संग्रह को बनाए रख सकता हूं ।
पर एक और मंच , पहले उत्तर अनुमति देने के लिए सुझाव Sword
के बारे में पता होना करने के लिए Reload
कुछ भी नहीं करते हैं,। यह वही उत्तर स्टैक ओवरफ्लो पृष्ठ पर दिया गया था जो मैं ऊपर से जुड़ा था।
मैं पूरी तरह से क्यों समझ में नहीं आता। सिद्धांत का उल्लंघन क्यों करें और तलवार को अवगत होने दें Reload
, और इसे खाली छोड़ दें? जैसा कि मैंने अपने स्टैक ओवरफ्लो पोस्ट में कहा था, एसपी, मेरी समस्याओं को बहुत हल करता है।
यह एक व्यवहार्य समाधान क्यों नहीं है?
public final Weapon{
private final String name;
private final int damage;
private final List<AttackStrategy> validactions;
private final List<Actions> standardActions;
private Weapon(String name, int damage, List<AttackStrategy> standardActions, List<Actions> attacks)
{
this.name = name;
this.damage = damage;
standardActions = new ArrayList<Actions>(standardActions);
validAttacks = new ArrayList<AttackStrategy>(validActions);
}
public void standardAction(String action){} // -- Can call reload or aim here.
public int attack(String action){} // - Call any actions that are attacks.
public static Weapon Sword(String name, damage, List<AttackStrategy> standardActions, List<Actions> attacks){
return new Weapon(name, damage,standardActions, attacks) ;
}
}
हमला इंटरफेस और कार्यान्वयन:
public interface AttackStrategy{
void attack(Enemy enemy);
}
public class Shoot implements AttackStrategy {
public void attack(Enemy enemy){
//code to shoot
}
}
public class Strike implements AttackStrategy {
public void attack(Enemy enemy){
//code to strike
}
}
reload()
खाली छोड़ दें या फिर standardActions
जिसमें पुनः लोड क्रिया न हो, बस एक अलग तंत्र है। कोई बुनियादी अंतर नहीं है। आप दोनों कर सकते हैं। => आपका समाधान है व्यवहार्य (जो आपके सवाल था) .; यदि हथियार में रिक्त डिफ़ॉल्ट कार्यान्वयन शामिल है, तो तलवार को पुनः लोड के बारे में जानने की आवश्यकता नहीं है।
class Weapon { bool supportsReload(); void reload(); }
। यदि पुन: लोड करने से पहले समर्थित है तो ग्राहक परीक्षण करेंगे।reload
iff फेंकने के लिए संविदात्मक रूप से परिभाषित किया गया है!supportsReload()
। यह एलएसपी iff संचालित कक्षाओं का पालन करता है प्रोटोकॉल मैं सिर्फ उल्लिखित का पालन करें।