c# यह स्पार्टा है, या यह है?




inheritance types (3)

निम्नलिखित एक साक्षात्कार सवाल है। मैं एक समाधान के साथ आया, लेकिन मुझे यकीन नहीं है कि यह क्यों काम करता है।

सवाल:

Sparta क्लास को संशोधित किए बिना, कुछ कोड लिखें जो MakeItReturnFalse false वापसी देता है।

public class Sparta : Place
{
    public bool MakeItReturnFalse()
    {
        return this is Sparta;
    }
}

मेरा समाधान: (स्पोइलर)

public class Place
{
public interface Sparta { }
}

लेकिन MakeItReturnFalse() में Sparta क्यों {namespace}.Place.Sparta संदर्भ देता है। {namespace}.Place.Sparta बजाय MakeItReturnFalse() SpartaSparta ?


लेकिन MakeItReturnFalse() में Sparta क्यों {namespace}.Place.Sparta संदर्भ देता है। {namespace}.Place.Sparta बजाय MakeItReturnFalse() SpartaSparta ?

असल में, क्योंकि नाम लुकअप नियम कहते हैं। सी # 5 विनिर्देशन में, प्रासंगिक नामकरण नियम खंड 3.8 ("नामस्थान और प्रकार के नाम") में हैं।

गोलियों के पहले जोड़े - छंटनी और एनोटेटेड - पढ़ें:

  • यदि नेमस्पेस-या-टाइप-नाम फॉर्म I<A1, ..., AK> फॉर्म I<A1, ..., AK> [इसलिए हमारे मामले में K = 0] है :
    • यदि के शून्य है और नामस्थान-या-प्रकार-नाम एक सामान्य विधि घोषणा के भीतर प्रकट होता है [नहीं, कोई सामान्य विधि नहीं]
    • अन्यथा, यदि नेमस्पेस-या-प्रकार-नाम किसी प्रकार की घोषणा के भीतर प्रकट होता है, तो प्रत्येक इंस्टेंस प्रकार के लिए टी (§10.3.1) टाइप करें, उस प्रकार की घोषणा प्रकार के उदाहरण के साथ शुरू होता है और प्रत्येक संलग्न वर्ग के उदाहरण प्रकार के साथ जारी रहता है या संरचना घोषणा (यदि कोई है):
      • यदि K शून्य है और T की घोषणा में नाम I साथ एक प्रकार पैरामीटर शामिल है, तो नामस्थान-या-प्रकार-नाम उस प्रकार पैरामीटर को संदर्भित करता है। [नहीं]
      • अन्यथा, यदि नेमस्पेस-या-प्रकार-नाम प्रकार की घोषणा के शरीर के भीतर प्रकट होता है, और T या उसके किसी भी मूल प्रकार में एक नेस्टेड सुलभ प्रकार होता है जिसमें नाम I और K प्रकार पैरामीटर होते हैं, तो नामस्थान-या-प्रकार-नाम दिए गए प्रकार के तर्कों के साथ उस प्रकार को संदर्भित करता है। [बिंगो!]
  • यदि पिछले चरण असफल होते हैं, तो प्रत्येक नेमस्पेस N , नामस्थान से शुरू होता है जिसमें नामस्थान-या-प्रकार-नाम होता है, प्रत्येक संलग्न नामस्थान (यदि कोई हो) के साथ जारी रहता है, और वैश्विक नामस्थान के साथ समाप्त होता है, तो निम्न चरण हैं एक इकाई स्थित होने तक मूल्यांकन किया जाता है:
    • यदि K शून्य है और I N में नामस्थान का नाम I , तो ... [हाँ, यह सफल होगा ]

तो अंतिम बुलेट प्वाइंट Sparta क्लास को उठाता है यदि पहली बुलेट को कुछ भी नहीं मिलता है ... लेकिन जब बेस क्लास Place एक इंटरफेस Sparta को परिभाषित करता है, तो Sparta क्लास पर विचार करने से पहले यह पाया जाता है।

ध्यान दें कि यदि आप नेस्टेड प्रकार Place.SpartaSparta को एक इंटरफ़ेस की बजाय कक्षा बनाते हैं, तो यह अभी भी संकलित करता है और false रिटर्न देता false - लेकिन कंपाइलर चेतावनी जारी करता है क्योंकि यह जानता है कि Sparta का एक उदाहरण क्लास Place.Sparta का उदाहरण नहीं होगा। Sparta । इसी प्रकार यदि आप Place.Sparta एक इंटरफ़ेस रखते हैं लेकिन Sparta क्लास को sealed , तो आपको एक चेतावनी मिलेगी क्योंकि कोई Sparta इंस्टेंस कभी इंटरफ़ेस को कार्यान्वित नहीं कर सकता है।


सुंदर सवाल! मैं उन लोगों के लिए थोड़ा सा स्पष्टीकरण जोड़ना चाहता हूं जो दैनिक आधार पर सी # नहीं करते हैं ... क्योंकि सवाल सामान्य रूप से नाम समाधान मुद्दों का एक अच्छा अनुस्मारक है।

मूल कोड लें, निम्न तरीकों से थोड़ा संशोधित करें:

  • आइए मूल अभिव्यक्ति के रूप में तुलना करने के बजाय टाइप नामों को प्रिंट करें (यानी return this is Sparta )।
  • आइए इंटरफ़ेस नाम रिज़ॉल्यूशन को चित्रित करने के लिए Place सुपरक्लास में इंटरफ़ेस Athena को परिभाषित करें।
  • आइए इसका टाइप नाम भी प्रिंट this क्योंकि यह Sparta क्लास में बाध्य है, बस सब कुछ स्पष्ट करने के लिए।

कोड इस तरह दिखता है:

public class Place {
    public interface Athena { }
}

public class Sparta : Place
{
    public void printTypeOfThis()
    {
        Console.WriteLine (this.GetType().Name);
    }

    public void printTypeOfSparta()
    {
        Console.WriteLine (typeof(Sparta));
    }

    public void printTypeOfAthena()
    {
        Console.WriteLine (typeof(Athena));
    }
}

अब हम Sparta ऑब्जेक्ट बनाते हैं और तीन विधियों को कॉल करते हैं।

public static void Main(string[] args)
    {
        Sparta s = new Sparta();
        s.printTypeOfThis();
        s.printTypeOfSparta();
        s.printTypeOfAthena();
    }
}

हमें जो उत्पादन मिलता है वह है:

Sparta
Athena
Place+Athena

हालांकि, अगर हम प्लेस क्लास को संशोधित करते हैं और इंटरफ़ेस स्पार्टा को परिभाषित करते हैं:

   public class Place {
        public interface Athena { }
        public interface Sparta { } 
    }

तो यह Sparta - इंटरफ़ेस है - जो नाम लुकअप तंत्र के लिए पहले उपलब्ध होगा और हमारे कोड का आउटपुट इस प्रकार बदल जाएगा:

Sparta
Place+Sparta
Place+Athena

इसलिए हमने MakeItReturnFalse में स्पार्टा इंटरफ़ेस को परिभाषित करके MakeItReturnFalse फ़ंक्शन परिभाषा में टाइप तुलना की तुलना में प्रभावी रूप से गड़बड़ कर ली है, जो पहले नाम रिज़ॉल्यूशन द्वारा पाया जाता है।

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


अपने मूल्य के नाम को हल करते समय परिभाषा के "निकटता" का प्रयोग अस्पष्टताओं को हल करने के लिए किया जाता है। जो भी परिभाषा "निकटतम" है जिसे चुना जाता है।

इंटरफेस Sparta को बेस क्लास के भीतर परिभाषित किया गया है। क्लास Sparta को नामस्थान में परिभाषित किया गया है। आधार वर्ग के भीतर परिभाषित चीजें एक ही नामस्थान में परिभाषित चीजों की तुलना में "करीब" हैं।







namespaces