इस बुरे OOP डिजाइन एक सिमुलेशन शामिल इंटरफेस के लिए है?


13

मैं पिशाच, भेड़ियों, मनुष्यों और ट्रकों को अनुकरण करने के लिए अपना खुद का थोड़ा ओओपी कार्यक्रम डिजाइन कर रहा हूं और इंटरफेसेस की अपनी सीमित समझ को लागू करने की कोशिश कर रहा हूं।

( मैं अभी भी यहाँ अमूर्त कर रहा हूँ और अभी तक कोई कोड कार्यान्वयन नहीं है, इसलिए यह OOP डिज़ाइन का प्रश्न है ... मुझे लगता है!)

क्या मैं इन वर्गों के बीच 'सामान्य व्यवहार' की तलाश में हूं और उन्हें इंटरफेस के रूप में लागू कर रहा हूं ?

उदाहरण के लिए, वैम्पायर और वॉल्व्स काटते हैं ... तो क्या मुझे एक काटने वाला इंटरफ़ेस होना चाहिए?

public class Vampire : Villain, IBite, IMove, IAttack

इसी तरह ट्रकों के लिए ...

public class Truck : Vehicle, IMove

और मनुष्य के लिए ...

public class Man : Human, IMove, IDead

क्या मेरी सोच यहीं है? (आपकी सहायता की सराहना)


14
पशु, सब्जियां और खनिज शायद ही कभी आवेदन के कार्यान्वयन के लिए अच्छे उदाहरण बनाते हैं। वास्तविक कार्यान्वयन आम तौर पर अधिक सार कर रहे हैं, जैसे IEnumerable, IEquatableआदि
रॉबर्ट हार्वे

6
आपके पास एक ही उल्लेख अपने वस्तुओं के लिए के बारे में क्या कर रहे हैं की कर ( "काटने") अपने सॉफ़्टवेयर में। सॉफ्टवेयर आमतौर पर कुछ करने के लिए डिज़ाइन किया गया है, विशेषताओं पर ऑब्जेक्ट मॉडल को आधार बनाकर केवल कहीं भी अग्रणी नहीं है।
टोफरो

@tofro मेरा इरादा था कि IBite में कई तरीके होंगे जो व्यवहार के बारे में लागू करेंगे (1) दूसरे के 'जीवन / ऊर्जा' के स्तर को कम करना (2) 'रक्त' ग्राफिक्स की उपस्थिति या आह्वान और (3) सिमुलेशन स्टैटिक्स का अद्यतन डेटा (जैसे NoOfBites)। मुझे लगता है कि मैं इस बात की सराहना कर सकता हूं कि कई तरीकों के व्यवहार को लागू करने के लिए एक इंटरफ़ेस का सबसे अच्छा उपयोग किया जाता है।
user3396486

2
क्या मानव, वैम्पायर और वाहन वर्ग पहले से ही IMove इंटरफ़ेस लागू नहीं करते हैं? आपको उपवर्गों को इसे बहुत ही विस्फोटक तरीके से लागू करने की आवश्यकता क्यों है?
पियरे अरलाउड

क्या यह सभी इंटरफेस वास्तव में आवश्यक हैं? पाइथन में सौभाग्य से आपको इस सामान की कोई आवश्यकता नहीं है, एह वास्तव में एक ताज़ा बदलाव था (मेरी पहली भाषा ऑब्जेक्ट पास्कल थी)। इसके अलावा कुछ मामलों में वर्चुअल तरीके बेहतर समाधान हो सकते हैं।
अजजा 12

जवाबों:


33

सामान्य तौर पर आप अपने क्लैस की सामान्य विशेषताओं के लिए इंटरफेस चाहते हैं।

मैं टिप्पणियों में @Robert हार्वे के साथ अर्ध-सहमत हूं, जिन्होंने कहा कि आमतौर पर इंटरफेस कक्षाओं की अधिक सार विशेषताओं का प्रतिनिधित्व करते हैं। फिर भी, मुझे लगता है कि अमूर्त सोचने के लिए शुरू करने का एक अच्छा तरीका अधिक ठोस उदाहरणों से शुरू होता है।

जबकि आपका उदाहरण तकनीकी रूप से सही है (यानी हाँ, पिशाच और भेड़िये दोनों काटते हैं, इसलिए आपके पास इसके लिए एक इंटरफ़ेस हो सकता है), प्रासंगिकता का सवाल है। प्रत्येक वस्तु में हजारों विशेषताएं होती हैं (जैसे जानवरों में फर हो सकता है, तैर सकता है, पेड़ों पर चढ़ सकता है, और इसी तरह)। क्या आप उन सभी के लिए एक इंटरफ़ेस बनाएंगे? बहुत कम संभावना है।

आप आमतौर पर उन चीजों के लिए इंटरफेस चाहते हैं, जो एक पूरे के रूप में एक आवेदन में समूहीकृत होने का मतलब है। उदाहरण के लिए, यदि आप कोई गेम बना रहे हैं, तो आपके पास IMove ऑब्जेक्ट्स की एक सरणी हो सकती है और उनकी स्थिति को अपडेट कर सकते हैं। यदि आप ऐसा नहीं करना चाहते हैं, तो IMove इंटरफ़ेस होना बहुत बेकार है।

बात यह है, इंजीनियर से अधिक नहीं है। आपको यह सोचने की आवश्यकता है कि आप उस इंटरफ़ेस का उपयोग कैसे करने जा रहे हैं, और 2 कक्षाएं सामान्य रूप से एक इंटरफ़ेस बनाने के लिए एक अच्छा पर्याप्त कारण नहीं है।


1
मुझे निश्चित रूप से उम्मीद है कि प्रत्येक वस्तु में हजारों विशेषताएँ नहीं हैं।
बाग़ का

4
ओप विशेषताओं में नहीं बल्कि व्याकरण की विशेषताओं / विशेषताओं में गुण (गुणकारी, तुलनीय, आदि): डी। शब्दों का बुरा विकल्प।
पॉल ४

3
ध्यान देने योग्य बात यह है कि जो इंटरफेस उपयोगी हैं, वे आपके द्वारा उपयोग किए जाने वाले हैं। उदाहरण के लिए, IBiteविशेष रूप से उपयोगी नहीं है, लेकिन आप चाहते हैं IAttackकि आप उन सभी चीजों पर काम कर सकते हैं जो हमले करते हैं, या IUpdateइसलिए आप हर चीज के लिए अपडेट चला सकते हैं, या IPhysicsEnabledइसलिए आप उन पर भौतिकी लागू कर सकते हैं, आदि
anaximander

1
यह उत्तर कुछ बहुत अच्छे बिंदुओं को उठाता है। अंतिम पैराग्राफ इसे अच्छी तरह से गाया जाता है; कम से कम और साथ ही आप प्रदान किए गए विवरण के स्तर के साथ कर सकते हैं।
ऑर्बिट

1
समूहन कॉमन्स विधियाँ अमूर्त वर्गों के लिए अधिक उपयुक्त हैं। इंटरफ़ेस अनुबंधों को डिज़ाइन करने के लिए बनाया गया है जो उन लोगों का सम्मान करना चाहिए जो इसे लागू करते हैं, कुछ वस्तुओं के लिए समान कार्यान्वयन को समूहीकृत नहीं करते हैं।
वल्फ्रैट

29

ऐसा लगता है कि आप एकल विधि इंटरफ़ेस का एक गुच्छा बना रहे हैं । यह उसके चेहरे पर ठीक है लेकिन ध्यान रखें कि इंटरफेस क्लास / तों के स्वामित्व में नहीं हैं जो उन्हें लागू करते हैं। वे उन ग्राहकों के स्वामित्व में हैं जो उनका उपयोग करते हैं। क्लाइंट तय करते हैं कि क्या कुछ ऐसा होना चाहिए जो आगे बढ़ सके और हमला कर सके।

यदि मेरे पास एक विधि के Combatसाथ एक वर्ग है fight(), तो उस विधि की संभावना दोनों को move()और attack()एक ही वस्तु पर कॉल करने की आवश्यकता है । यह दृढ़ता से एक ICombatantइंटरफ़ेस की आवश्यकता का सुझाव देता है जो fight()कॉल कर सकता है move()और जिसके attack()माध्यम से। यह fight()एक IAttackऑब्जेक्ट लेने और इसे IMoveदेखने के लिए कास्टिंग करने की तुलना में क्लीनर है अगर यह भी स्थानांतरित कर सकता है।

इसका मतलब यह नहीं है कि आप IMove IAttackइंटरफेस भी नहीं कर सकते हैं । मुझे उम्मीद है कि आप उन्हें बिना किसी क्लाइंट की जरूरत के नहीं बना रहे होंगे। इसके विपरीत, यदि किसी ग्राहक को कभी भी वस्तु को हिलाने और हमला ICombatantकरने की आवश्यकता नहीं होती है तो उसकी आवश्यकता नहीं होती है।

इंटरफेस देखने का यह सरल तरीका अक्सर खो जाता है क्योंकि लोग निम्नलिखित उदाहरणों को पसंद करते हैं। पहला इंटरफेस जो हम उजागर कर रहे हैं, वे पुस्तकालयों में हैं। दुर्भाग्य से, पुस्तकालयों को पता नहीं है कि उनके ग्राहक क्या हैं। इसलिए वे केवल अपने ग्राहकों की जरूरतों का अनुमान लगा सकते हैं। पालन ​​करने के लिए सबसे अच्छा उदाहरण नहीं।


1
लानत है यह अच्छा है। गेमिंग बस OOP का उपयोग करने और समझाने के लिए एक बहुत अच्छा तरीका है।
जेफ़ओ

7
@JeffO जब तक आप वास्तव में एक बड़े खेल को लागू नहीं करते हैं और महसूस करते हैं कि OOP एक गर्म गड़बड़ है और आप घटक-आधारित सिस्टम या डेटा-उन्मुख डिज़ाइन के साथ बेहतर होंगे।
डार्कहॉग सेप

"इंटरफेस उन ग्राहकों के स्वामित्व में हैं जो उनका उपयोग करते हैं"
टिबोस


1
पुस्तकालयों और अनुप्रयोग के बीच अंतर के लिए +1, मैं अक्सर (बहुत अधिक ?: /) उन चीजों को पढ़ता हूं जो सिर्फ एक के लिए फिट होती हैं और दूसरे के लिए नहीं।
वालफ्रैट

3

विचार करें कि क्या क्षमताओं के विभिन्न संयोजनों के साथ वस्तुओं का संग्रह करना आम होगा, और क्या कोड उन वस्तुओं पर कार्रवाई करना चाहते हैं , जो एक संग्रह के भीतर हैं, जो इसका समर्थन करते हैं । यदि ऐसा है, और अगर वस्तुओं के लिए एक समझदार "डिफ़ॉल्ट व्यवहार" होगा जो कुछ कार्रवाई के लिए उपयोगी समर्थन नहीं है, तो यह वर्गों की एक विस्तृत श्रृंखला द्वारा लागू इंटरफेस के लिए उपयोगी हो सकता है, न कि केवल उन लोगों के लिए जो उपयोगी व्यवहार कर सकते हैं।

उदाहरण के लिए, मान लें कि केवल कुछ प्रकार के प्राणी Woozles हो सकते हैं, और एक व्यक्ति चाहता है कि उसके पास एक NumerOfWoozlesसंपत्ति हो। यदि ऐसी संपत्ति एक ऐसे इंटरफ़ेस में थी जो केवल जीवों द्वारा लागू की गई थी, जिसमें Woozles हो सकते हैं, तो कोड जो मिश्रित प्रकार के प्राणियों के संग्रह द्वारा आयोजित Woozles की कुल संख्या का पता लगाना चाहता था, उसे कुछ कहना होगा:

int total = 0;
foreach (object it in creatures)
{
   IWoozleCountable w = trycast(it, IWoozleCountable);
   if (w != null) total += w.WoozleCount;
}

यदि, हालांकि, WoozleCount प्राणी / ICreature का सदस्य था, भले ही कुछ उपप्रकार प्राणी के डिफ़ॉल्ट WoozleCount कार्यान्वयन को हमेशा के लिए समाप्त कर देगा, जो कोड को शून्य देता है:

int total = 0;
foreach (ICreature it in creatures)
   total += it.WoozleCount;

हालांकि कुछ लोग प्रत्येक प्राणी को एक WoozleCount संपत्ति को लागू करने के विचार पर झगड़ सकते हैं, जो वास्तव में केवल कुछ उपप्रकारों के लिए उपयोगी है, संपत्ति सभी प्रकारों के लिए सार्थक होगी , चाहे वह उन प्रकारों से ज्ञात वस्तुओं के साथ उपयोगी हो, या नहीं और मैं "किचन सिंक" इंटरफेस के संबंध में कोशिश करूंगा कि कोडकोर ऑपरेटर की तुलना में कोड गंध कम हो।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.