विरासत को कब रोकना है?


9

एक बार पहले मैंने विरासत के बारे में स्टैक ओवरफ्लो पर एक प्रश्न पूछा था ।

मैंने कहा है कि मैं OOP फैशन में शतरंज का इंजन डिजाइन करता हूं। इसलिए मुझे अपने सभी टुकड़े पीस एब्स्ट्रैक्ट क्लास से विरासत में मिले लेकिन विरासत अभी भी है। मुझे कोड करके दिखाओ

public abstract class Piece
{
    public void MakeMove();
    public void TakeBackMove();
}

public abstract class Pawn: Piece {}

public class WhitePawn :Pawn {}

public class BlackPawn:Pawn {}

प्रोग्रामर को मेरा डिज़ाइन इंजीनियरिंग से थोड़ा सा मिल गया है और नीचे की तरह एक संपत्ति के सदस्य के रूप में रंगीन रंग की कक्षाएं हटाने और टुकड़ा रंग धारण करने का सुझाव दिया गया है।

public abstract class Piece
{
    public Color Color { get; set; }
    public abstract void MakeMove();
    public abstract void TakeBackMove();
}

इस तरह से टुकड़ा उसका रंग जान सकता है। कार्यान्वयन के बाद मैंने देखा कि मेरा कार्यान्वयन नीचे की तरह हो जाता है।

public abstract class Pawn: Piece
{
    public override void MakeMove()
    {
        if (this.Color == Color.White)
        {

        }
        else
        {

        }
    }

    public override void TakeBackMove()
    {
        if (this.Color == Color.White)
        {

        }
        else
        {

        }
    }
}

अब मैं देख रहा हूं कि कार्यान्वयन में बयानों के कारण रंग संपत्ति को बनाए रखें। यह मुझे लगता है कि हमें विरासत के पदानुक्रम में विशिष्ट रंग के टुकड़े की आवश्यकता है।

ऐसे में क्या आपके पास व्हाइटपॉन, ब्लैकपॉन जैसी कक्षाएं होंगी या आप कलर प्रॉपर्टी रखकर डिजाइन करने जाएंगे?

इस तरह की समस्या को देखे बिना आप डिजाइन कैसे शुरू करना चाहेंगे? रंग संपत्ति रखें या वंशानुक्रम समाधान करें?

संपादित करें: मैं यह निर्दिष्ट करना चाहता हूं कि मेरा उदाहरण वास्तविक जीवन के उदाहरण से पूरी तरह मेल नहीं खा सकता है। इसलिए कार्यान्वयन विवरण का अनुमान लगाने से पहले सिर्फ सवाल पर ध्यान केंद्रित करें।

मैं वास्तव में केवल यह पूछ रहा हूं कि क्या विरासत में उपयोग करने के लिए स्टेटमेंट का उपयोग करने के लिए कलर प्रॉपर्टी का उपयोग करना बेहतर होगा?


3
मुझे वास्तव में समझ में नहीं आया कि आप इस तरह से टुकड़ों को क्यों मॉडल करेंगे। जब आप MakeMove () कहते हैं, तो यह कौन सा कदम बनाएगा? मैं कहता हूं कि आपको वास्तव में बोर्ड के राज्य के साथ शुरुआत करने की आवश्यकता है और देखें कि आपको इसके लिए कौन सी कक्षाएं चाहिए
jk।

11
मुझे लगता है कि आपकी मूल ग़लतफ़हमी का एहसास नहीं है कि शतरंज में "रंग" टुकड़ा के बजाय खिलाड़ी का वास्तव में एक विशेषता है। इसलिए हम कहते हैं "अश्वेतों की चाल" इत्यादि, रंग वहाँ है कि कौन सा खिलाड़ी किस मालिक के टुकड़े की पहचान करे। एक मोहरा एक ही आंदोलन के नियमों का पालन करता है और कोई फर्क नहीं पड़ता कि यह किस रंग का है केवल भिन्नता है जो दिशा "आगे" है।
जेम्स एंडरसन

5
जब आप "विरासत को रोकने के लिए" कब आंकड़ा नहीं कर सकते, तो इसे पूरी तरह से छोड़ दें। जब आप पदानुक्रम आपके लिए स्पष्ट हो जाएंगे, तो आप बाद के डिज़ाइन / कार्यान्वयन / रखरखाव चरण पर विरासत को फिर से पेश कर सकते हैं। मैं इस दृष्टिकोण का उपयोग करता हूं, एक आकर्षण की तरह काम करता है
gnat

1
अधिक चुनौतीपूर्ण मुद्दा यह है कि प्रत्येक टुकड़ा प्रकार के लिए एक उप-वर्ग बनाना है या नहीं। टुकड़ा प्रकार टुकड़ा रंग की तुलना में अधिक व्यवहार पहलुओं को निर्धारित करता है।
NoChance

3
यदि आप ABCs (एब्सट्रैक्ट बेस क्लासेस) के साथ एक डिज़ाइन शुरू करने के लिए ललचाते हैं, तो हम सभी पर एक एहसान करते हैं और नहीं ... एबीसी वास्तव में उपयोगी होते हैं और तब भी, यह आमतौर पर एक इंटरफ़ेस का उपयोग करने के लिए अधिक उपयोगी होता है बजाय।
इवान प्लाइस

जवाबों:


12

कल्पना कीजिए कि आप एक एप्लिकेशन डिज़ाइन करते हैं जिसमें वाहन शामिल हैं। क्या आप ऐसा कुछ बनाते हैं?

class BlackVehicle : Vehicle { }
class DarkBlueVehicle : Vehicle { }
class DarkGreenVehicle : Vehicle { }
// hundreds of other classes...

वास्तविक जीवन में, रंग एक वस्तु (या तो एक कार या शतरंज का टुकड़ा) की एक संपत्ति है, और एक संपत्ति का प्रतिनिधित्व करना चाहिए।

क्या अश्वेतों और गोरों के लिए अलग MakeMove- TakeBackMoveअलग हैं? बिल्कुल नहीं: नियम दोनों खिलाड़ियों के लिए समान हैं, जिसका अर्थ है कि वे दो विधियां अश्वेतों और गोरों के लिए बिल्कुल समान होंगी , जिसका अर्थ है कि आप एक ऐसी स्थिति जोड़ रहे हैं जहां आपको इसकी आवश्यकता नहीं है।

दूसरी ओर, यदि आपके पास है WhitePawnऔर BlackPawn, मुझे आश्चर्य नहीं होगा अगर जल्द ही या बाद में आप लिखेंगे:

var piece = (Pawn)this.CurrentPiece;
if (piece is WhitePawn)
{
}
else // The pice is of type BlackPawn
{
}

या यहां तक ​​कि जैसे कुछ:

public abstract class Pawn
{
    public Color Player
    {
        get
        {
            return this is WhitePawn ? Color.White : Color.Black;
        }
    }
}

// Now imagine doing the same thing for every other piece.

4
@ फ्रेशब्लड मुझे लगता है कि directionप्रॉपर्टी का इस्तेमाल करना बेहतर होगा और कलर प्रॉपर्टी का इस्तेमाल करने की तुलना में आगे बढ़ना होगा। रंग आदर्श रूप से केवल रेंडरिंग के लिए उपयोग किया जाना चाहिए, तर्क के लिए नहीं।
ज्ञान उर्फ ​​गैरी ब्यून

7
इसके अलावा, टुकड़े एक ही दिशा में आगे, पीछे, बाएं, दाएं चलते हैं। अंतर बोर्ड के किस तरफ से शुरू होता है। एक सड़क पर, विरोधी गलियों में कारें दोनों आगे बढ़ती हैं।
स्लिपसेट

1
@ ब्लरफ्ल आप सही हो सकते हैं कि directionसंपत्ति एक बूलियन है। मुझे नहीं लगता कि इसमें क्या गलत है। जब तक फ्रेशब्लड की टिप्पणी ऊपर है तब तक मुझे इस बारे में उलझन क्यों है कि वह रंग के आधार पर आंदोलन के तर्क को कैसे बदलना चाहते हैं। मैं कहूंगा कि यह समझना अधिक कठिन है क्योंकि यह व्यवहार के लिए रंग के लिए कोई मतलब नहीं है। यदि आप सब करना चाहते हैं, तो भेद करें कि कौन सा खिलाड़ी किस टुकड़े का मालिक है, आप उन्हें दो अलग-अलग संग्रहों में डाल सकते हैं और एक संपत्ति या विरासत की आवश्यकता से बच सकते हैं। टुकड़े स्वयं आनंदित हो सकते हैं कि वे किस खिलाड़ी से अनजान हैं।
ज्ञान उर्फ ​​गैरी ब्यन

1
मुझे लगता है कि हम एक ही चीज को दो अलग-अलग दृष्टिकोणों से देख रहे हैं। यदि दोनों पक्ष लाल और नीले होते तो क्या उनका व्यवहार काला और सफेद होने पर अलग होता? मैं नहीं कहूंगा, यही कारण है कि मैं कह रहा हूं कि रंग किसी भी व्यवहार के अंतर का कारण नहीं है। यह केवल एक सूक्ष्म अंतर है लेकिन यही कारण है कि मैं खेल तर्क में एक के बजाय एक directionया शायद एक playerसंपत्ति का उपयोग करूंगा color
ज्ञान उर्फ ​​गैरी ब्यून

1
@ फ्रेशबल्ड white castle's moves differ from black's- कैसे? क्या आपका मतलब है कास्टलिंग? किंग-साइड कास्टिंग और क्वीन-साइड कास्टिंग दोनों ब्लैक एंड व्हाइट के लिए 100% सममित हैं।
कोनराड मोरावस्की

4

आपको खुद से यह पूछना चाहिए कि आपको अपने प्यादा वर्ग में उन बयानों की आवश्यकता क्यों है:

    if (this.Color == Color.White)
    {

    }
    else
    {
    }

मुझे पूरा यकीन है कि इस तरह के कार्यों का एक छोटा समूह होना पर्याप्त होगा

public abstract class Piece
{
    bool DoesPieceHaveSameColor(Piece otherPiece) { /*...*/   }

    Color OtherColor{get{/*...*/}}
    // ...
}

अपने टुकड़ा वर्ग में और उन कार्यों का उपयोग करके Pawn(और अन्य व्युत्पत्तियों के Piece) सभी कार्यों को कार्यान्वित करें , ifऊपर दिए गए उन कथनों के बिना । केवल अपवाद इसके रंग द्वारा प्यादा के लिए चाल की दिशा निर्धारित करने का कार्य हो सकता है, क्योंकि यह प्यादों के लिए विशिष्ट है, लेकिन लगभग सभी अन्य मामलों में आपको किसी भी रंग-विशिष्ट कोड की आवश्यकता नहीं होगी।

अन्य दिलचस्प सवाल यह है कि क्या आपको वास्तव में विभिन्न प्रकार के टुकड़ों के लिए अलग उपवर्ग होना चाहिए। यह मेरे लिए उचित और स्वाभाविक लगता है, क्योंकि प्रत्येक टुकड़े के लिए चाल के नियम अलग-अलग होते हैं और आप निश्चित रूप से प्रत्येक प्रकार के टुकड़े के लिए अलग-अलग ओवरलोड कार्यों का उपयोग करके इसे लागू कर सकते हैं।

बेशक, एक एक अधिक सामान्य तरीके से इस मॉडल के लिए, उनके आगे बढ़ नियमों से टुकड़े के गुणों को अलग करके की कोशिश कर सकते हैं, लेकिन यह एक अमूर्त वर्ग में खत्म हो सकता है MovingRuleऔर एक उपवर्ग पदानुक्रम MovingRulePawn, MovingRuleQueen, ... मैं इसे शुरू नहीं होता है कि जिस तरह से, यह आसानी से ओवर-इंजीनियरिंग के दूसरे रूप को जन्म दे सकता है।


+1 यह इंगित करने के लिए कि रंग-विशिष्ट कोड संभवतः कोई नहीं है। सफेद और काले प्यादे अनिवार्य रूप से उसी तरह व्यवहार करते हैं, जैसे अन्य सभी टुकड़े।
कोनराड मोरावस्की

2

जब वस्तु वस्तु की बाहरी क्षमताओं को प्रभावित नहीं करती है तो इनहेरिटेंस उतना उपयोगी नहीं है

कलर प्रॉपर्टी पर कोई असर नहीं पड़ता है कि कैसे एक ऑब्जेक्ट का उपयोग किया जाता है । उदाहरण के लिए, सभी टुकड़े एक चालन या चालन विधि को लागू कर सकते हैं (भले ही चाल कानूनी न हो), लेकिन टुकड़ा का तर्क तर्क निरपेक्ष या पीछे की ओर गति का प्रतिनिधित्व करने वाले निरपेक्ष मान को निर्धारित करने के लिए रंग गुण का उपयोग करता है (-1 या +) 1 पर "y अक्ष"), जहां तक ​​आपके एपीआई का संबंध है, आपके सुपरक्लास और उपवर्ग समान वस्तुएं हैं (क्योंकि वे सभी समान विधियों को उजागर करते हैं)।

व्यक्तिगत रूप से, मैं कुछ स्थिरांक को परिभाषित करूँगा जो प्रत्येक टुकड़ा प्रकार का प्रतिनिधित्व करते हैं, फिर निजी तरीकों से शाखा में स्विच स्टेटमेंट का उपयोग करते हैं जो "" "उदाहरण के लिए संभावित चालें लौटाता है।


प्यादों के मामले में पिछड़ा आंदोलन केवल अवैध है। और उन्हें वास्तव में यह जानने की जरूरत नहीं है कि वे काले या सफेद हैं - यह पर्याप्त (और तार्किक) है कि वे उन्हें आगे और पीछे बनाम अलग कर सकें। Boardवर्ग (उदाहरण के लिए) में -1 इन अवधारणाओं को परिवर्तित करने या +1 टुकड़ा के रंग पर निर्भर करता है के आरोप में हो सकता है।
कोनराड मोरावस्की

0

व्यक्तिगत रूप से मुझे कुछ भी विरासत में नहीं मिलेगा Piece, क्योंकि मुझे नहीं लगता कि आप ऐसा करने से कुछ हासिल करते हैं। संभवतः एक टुकड़ा वास्तव में परवाह नहीं करता है कि यह कैसे चलता है, केवल कौन सा वर्ग इसकी अगली चाल के लिए एक वैध गंतव्य है।

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

interface IMoveCalculator
{
    List<Square> GetValidDestinations();
}

class KnightMoveCalculator : IMoveCalculator;
class QueenMoveCalculator : IMoveCalculator;
class PawnMoveCalculator : IMoveCalculator; 
// etc.

class Piece
{
    IMoveCalculator move_calculator;
public:
    Piece(IMoveCalculator mc) : move_calculator(mc) {}
}

लेकिन कौन निर्धारित करता है कि कौन सा टुकड़ा कैलकुलेटर को स्थानांतरित करता है? यदि आपके पास एक टुकड़ा आधार वर्ग था, और प्यादापैन था, तो आप यह अनुमान लगा सकते हैं। लेकिन फिर उस दर पर, टुकड़ा ही लागू कर सकता है कि यह कैसे चलता है, जैसा कि मूल प्रश्न में डिज़ाइन किया गया है
स्टीवन स्ट्रिगा

@EekendWarrior - "व्यक्तिगत रूप से मुझे कुछ भी विरासत में नहीं मिला Piece"। ऐसा लगता है कि टुकड़ा चालों की गणना करने से अधिक के लिए जिम्मेदार है, जो एक अलग चिंता के रूप में आंदोलन को विभाजित करने का कारण है। कौन सा टुकड़ा किस कैलकुलेटर पर निर्भरता इंजेक्शन की बात होगी, यह निर्धारित करना, जैसेvar my_knight = new Piece(new KnightMoveCalculator())
बेन कॉटरेल

यह फ्लाईवेट पैटर्न के लिए एक अच्छा उम्मीदवार होगा। एक शतरंज की बिसात पर 16 प्यादे हैं और वे सभी एक ही व्यवहार को साझा करते हैं । इस व्यवहार को आसानी से एक एकल फ्लाईवेट में निकाला जा सकता है। वही अन्य सभी टुकड़ों के लिए जाता है।
मैटवेवी

-2

इस उत्तर में, मैं मान रहा हूं कि "शतरंज इंजन" द्वारा, प्रश्न के लेखक का अर्थ "शतरंज एआई" है, न कि केवल एक चाल सत्यापन इंजन।

मुझे लगता है कि टुकड़ों के लिए OOP का उपयोग करना और उनकी वैध चालन दो कारणों से एक बुरा विचार है:

  1. एक शतरंज इंजन की ताकत इस बात पर अत्यधिक निर्भर है कि यह कितनी तेजी से बोर्डों में हेरफेर कर सकता है, उदाहरण के लिए शतरंज कार्यक्रम बोर्ड का प्रतिनिधित्व । इस लेख के अनुकूलन के स्तर को देखते हुए, मुझे नहीं लगता कि एक नियमित फ़ंक्शन कॉल सस्ती है। एक आभासी विधि के लिए एक कॉल अप्रत्यक्ष के स्तर को जोड़ देगा और एक उच्च प्रदर्शन जुर्माना भी लगाएगा। OOP की लागत वहाँ सस्ती नहीं है।
  2. OOP के लाभ जैसे कि एक्स्टेंसिबिलिटी टुकड़ों के लिए कोई फायदा नहीं है, क्योंकि शतरंज में जल्द ही नए टुकड़े मिलने की संभावना नहीं है। वंशानुक्रम आधारित प्रकार पदानुक्रम के लिए एक व्यवहार्य विकल्प में एनम और स्विच का उपयोग करना शामिल है। बहुत कम तकनीक और सी-लाइक, लेकिन प्रदर्शन-वार को हराने के लिए कठिन।

प्रदर्शन के विचारों से हटकर, प्रकार के पदानुक्रम में टुकड़े का रंग सहित, मेरी राय में एक बुरा विचार है। आप अपने आप को उन स्थितियों में पाएंगे जहां आपको जांचने की ज़रूरत है कि क्या दो टुकड़ों में अलग-अलग रंग हैं, उदाहरण के लिए कैप्चरिंग के लिए। संपत्ति का उपयोग करके इस स्थिति की जांच आसानी से की जाती है। इसका उपयोग करना is WhitePiece-tests तुलना में बदसूरत होगा।

चलती-फिरती पीढ़ी को टुकड़ा-विशिष्ट तरीकों से बचने के लिए एक और व्यावहारिक कारण भी है, अर्थात् विभिन्न टुकड़े आम चालें साझा करते हैं, जैसे कि बदमाश और रानी। डुप्लिकेट कोड से बचने के लिए, आपको कॉमन कोड को आधार विधि में बदलना होगा, और अभी तक एक और महंगा कॉल करना होगा।

यह कहा जा रहा है, अगर यह पहला शतरंज इंजन है जिसे आप लिख रहे हैं, तो मैं निश्चित रूप से स्वच्छ प्रोग्रामिंग सिद्धांतों के साथ जाने और Crafty के लेखक द्वारा वर्णित अनुकूलन चाल से बचने की सलाह दूंगा। शतरंज के नियमों (कास्टलिंग, प्रमोशन, एन-पासेंट) और जटिल एआई तकनीकों (हैशिंग बोर्ड, अल्फा-बीटा कट) की बारीकियों से निपटना काफी चुनौतीपूर्ण है।


1
हो सकता है कि शतरंज का इंजन बहुत तेजी से लिखने का उद्देश्य न हो।
फ्रेशब्लड

5
-1। "काल्पनिक रूप से यह एक प्रदर्शन मुद्दा बन सकता है, इसलिए यह खराब है" जैसे निर्णय, IMHO लगभग हमेशा शुद्ध अंधविश्वास हैं। और विरासत सिर्फ "विलुप्तता" के बारे में नहीं है, जिस अर्थ में आप इसका उल्लेख करते हैं। अलग-अलग शतरंज के नियम अलग-अलग टुकड़ों पर लागू होते हैं, और हर तरह के टुकड़े का अलग-अलग तरीके से लागू WhichMovesArePossibleहोना एक उचित तरीका है।
डॉक्टर ब्राउन

2
यदि आपको एक्स्टेंसिबिलिटी की आवश्यकता नहीं है, तो स्विच / एनम पर आधारित एक दृष्टिकोण बेहतर है क्योंकि यह वर्चुअल विधि प्रेषण से अधिक तेज़ है। एक शतरंज इंजन सीपीयू-भारी है, और जो ऑपरेशन सबसे अधिक बार किए जाते हैं (और इसलिए दक्षता महत्वपूर्ण) चालें प्रदर्शन कर रहे हैं और उन्हें पूर्ववत कर रहे हैं। बस एक स्तर ऊपर जो सभी संभावित चालों को सूचीबद्ध करता है। मुझे उम्मीद है कि यह समय भी महत्वपूर्ण होगा। तथ्य यह है, मैंने सी में शतरंज इंजनों को क्रमादेशित किया है। ओओपी के बिना भी, बोर्ड प्रतिनिधित्व पर निम्न-स्तरीय अनुकूलन महत्वपूर्ण थे। किस तरह का अनुभव आपको ख़ारिज करना है?
जोह

2
@ जो: मैं आपके अनुभव का अनादर नहीं करूंगा, लेकिन मुझे पूरा यकीन है कि ओपी के बाद ऐसा नहीं था। और यद्यपि निम्न-स्तरीय अनुकूलन कई समस्याओं के लिए महत्वपूर्ण हो सकते हैं, मैं इसे उच्च-स्तरीय डिज़ाइन निर्णयों के लिए एक आधार बनाने के लिए एक गलती के रूप में मानता हूं - खासकर जब कोई अभी तक किसी भी प्रदर्शन के मुद्दों का सामना नहीं करता है। मेरा अनुभव है कि "समय से पहले अनुकूलन सभी बुराई की जड़ है।"
डॉक ब्राउन

1
-1 मुझे डॉक्टर से सहमत होना होगा। तथ्य यह है, यह "इंजन" ओपी के बारे में बात कर रहा है, बस 2 खिलाड़ी शतरंज के खेल के लिए सत्यापन इंजन हो सकता है। उस मामले में, ओओपी बनाम किसी अन्य शैली के प्रदर्शन के बारे में सोचना पूरी तरह से अजीब है, क्षणों की सरल मान्यताएं कम अंत एआरएम डिवाइस पर भी मिलीसेकंड ले जाएंगी। वास्तव में बताई गई आवश्यकताओं से अधिक न पढ़ें।
टिमोथी बाल्ड्रिज
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.