2009-07-23 9 views
16

मैं एक अमूर्त वर्ग है, AbsClass कि एक अंतरफलक को लागू करता है, IClass साथ एक अमूर्त वर्ग से निकला में एक संपत्ति के लिए एक सेट एक्सेसर जोड़ा जा रहा है। आईसीएलएएस में कुछ गुण हैं जो केवल एक्सेसर्स प्राप्त करते हैं। AbsClassआईसीएलएएस के गुणों को AbsClass से प्राप्त कक्षाओं में परिभाषित करने के लिए सार गुणों के रूप में लागू करता है।एक वर्ग है कि केवल एक बात एक्सेसर

तो कक्षाएं कि से निकाले जाते हैं AbsClass के सभी भी प्राप्त accessors के साथ एक ही गुण होने से IClass को संतुष्ट करने की आवश्यकता होगी। हालांकि, कुछ मामलों में मैं आईसीएलएएस से गुणों में सेट एक्सेसर्स जोड़ने में सक्षम होना चाहता हूं। फिर भी अगर मैं एक सेट एक्सेसर मैं यह त्रुटि

ConcClassA.Bottom.Set ओवरराइड नहीं कर सकते क्योंकि AbsClass.Bottom एक overridable सेट एक्सेसर नहीं है

देखें पाने के साथ AbsClassमें सार गुण को ओवरराइड करने की कोशिश ConcClassA नीचे।

यदि मेरे पास एक कक्षा है जो केवल आईसीएलएएस इंटरफ़ेस को कार्यान्वित कर रही है, लेकिन AbsClass से विरासत में नहीं है तो मैं बाहर समस्याओं के साथ एक सेट एक्सेसर जोड़ने में सक्षम हूं। नीचे ConcClassB देखें।

मैं केवल AbsClass के लिए सीधे AbsClass के प्रत्येक व्युत्पन्न पर आईसीएलएएस लागू कर सकता हूं। फिर भी मुझे अपने डिजाइन से पता है कि प्रत्येक AbsClass को आईसीएलएएस भी होना चाहिए, इसलिए मैं पदानुक्रम में उच्च निर्दिष्ट करना चाहता हूं।

public interface IClass 
{ 
    double Top 
    { 
     get; 
    } 
    double Bottom 
    { 
     get; 
    } 
} 

abstract class AbsClass:IClass 
{ 
    public abstract double Top 
    { 
     get; 
    } 

    public abstract double Bottom 
    { 
     get; 
    } 
} 



class ConcClassA : AbsClass 
{ 
    public override double Top 
    { 
     get { return 1; } 
    } 

    public override double Bottom 
    { 
     get { return 1; } 

     //adding a Set accessor causes error: 
     //ConcClassA.Bottom.Set cannot override because AbsClass.Bottom does not have an overridable set accessor 

     //set { } 
    } 

} 

class ConcClassB : IClass 
{ 
    public double Top 
    { 
     get { return 1; } 
     //added a set accessor to an interface does not cause problem 
     set { } 
    } 
    public double Bottom 
    { 
     get { return 1; } 
    } 
} 

अद्यतन

तो मुझे लगता है यह और अधिक समझ कर देगा अगर मैं वास्तव में क्या मैं तो बल्कि ऐसा करने के लिए सार उदाहरण का उपयोग कोशिश कर रहा हूँ की व्याख्या। मैं एक आर्किटेक्चर फर्म के लिए काम करता हूं और ये एक वास्तुकला डिजाइन परियोजना से संबंधित व्यावसायिक वस्तुएं हैं।

मेरे पास एक अमूर्त वर्ग RhNodeBuilding है जो किसी प्रोजेक्ट पर एक प्रकार की इमारत का प्रतिनिधित्व करता है। कुछ सामान्य कार्यक्षमताएं हैं, जैसे फर्श रखने की क्षमता, जिसे RhNodeBuilding में परिभाषित किया गया है। RhNodebuilding भी एक अन्य अमूर्त वर्गों से विरासत में मिलता है जो इसे एक बड़ी परियोजना वृक्ष संरचना का हिस्सा बनने की अनुमति देता है।

RhNodeBuilding एक अंतरफलक IBuilding जो केवल पढ़ने के लिए गुण है कि सभी भवनों प्रदान करने के लिए सक्षम होना चाहिए की एक संख्या को परिभाषित करता है से लागू इस तरह के TopElevation, BottomElevation, ऊंचाई, NumberOfFloors के रूप में, आदि ।आदि..ध्यान रखें कि ऐसे अन्य भवन प्रकार हैं जो RhNodeBuilding से प्राप्त नहीं होते हैं, लेकिन अभी भी लागू करने की आवश्यकता है I12ildingMassBuilding और FootPrintBuilding:

अभी मैं दो प्रकार कि RhNodeBuilding से निकाले जाते हैं की है। Massbuilding उपयोगकर्ता द्वारा बनाए गए 3 डी आकार द्वारा परिभाषित किया गया है। उस आकार में शीर्ष ऊंचाई और नीचे की ऊंचाई जो संबंधित गुणों के माध्यम से सुलभ होनी चाहिए, लेकिन आप गुणों को बदलकर 3 डी वॉल्यूम को संपादित करने में सक्षम नहीं होना चाहिए।

फुटप्रिंट बिल्डिंग दूसरी ओर एक बंद वक्र और ऊंचाई वक्र द्वारा परिभाषित किया गया है जिससे वक्र को बाहर निकाला जा सके। इसलिए न केवल कक्षा को मौजूदा ऊंचाईों को वापस करने में सक्षम होना चाहिए, बल्कि इन ऊंचाईों को ऊंचाई सीमा को फिर से परिभाषित करने के लिए भी बदला जा सकता है।

तो संक्षेप में। सभी इमारतों (IBuildings) एक TopElevation और BottomElevation लौटने में सक्षम होने की जरूरत है, लेकिन सभी भवनों TopElevation या BottomElevation सीधे सेट करने के लिए अनुमति चाहिए। सभी RhNodeBuildingsIBuildings, और वर्गों है कि RhNodeBuilding से निकाले जाते हैं या जरूरत नहीं हो सकता है कर रहे हैं सक्षम सीधे सेट करने के लिए TopElevation और BottomElevation किया जाना है।

public interface IBuilding 
{ 
    double Top 
    { 
     get; 
    } 
    double Bottom 
    { 
     get; 
    } 
} 

abstract class RhNodeBuilding:IBuilding 
{ 
    public abstract double Top 
    { 
     get; 
    } 

    public abstract double Bottom 
    { 
     get; 
    } 
} 



class MassBuilding: AbsClass 
{ 

    //mass building only returns Top and Bottom properties so it works fine 
    public override double Bottom 
    { 
     get { return 1; } 
    } 

    public override double Top 
    { 
     get { return 1; } 
    } 

} 


class FootPrintBuilding: AbsClass 
{ 
    //Top and Bottom of FootPrintBuilding can both be retrieved and set 
    public override double Top 
    { 
     get { return 1; } 
     //adding a Set accessor causes error: 
     //cannot override because RhNodeBuilding.Top does not have an overridable set accessor 

     //set { } 
    } 

    public override double Bottom 
    { 
     get { return 1; } 

     //adding a Set accessor causes error: 
     //cannot override because RhNodeBuilding.Bottom does not have an overridable set accessor 

     //set { } 
    } 

} 

अभी ऐसा लगता है सबसे अच्छा विकल्प RhNodeBuilding लागू IBuilding नहीं करने के लिए है, बल्कि हर वर्ग कि RhNodeBuilding से निकला IBuilding को लागू किया है। इस तरह से मैं से को सीधे ओवरराइड के रूप में गुणों को परिभाषित कर सकता हूं।

abstract class AltRhNodeBuilding 
{ 
    public abstract double Top 
    { 
     get; 
    } 
} 


class AltFootPrintBuilding: IClass 
{ 
    public override double Top 
    { 
     get { return 1; } 

     //Can't add set access to overridden abstract property 
     set { } 
    } 

    //No problem adding set accessor to interface property 
    public double Bottom 
    { 
     get { return 1; } 
     set { } 
    } 
} 
+0

क्या आप यह कहते हुए इंटरफ़ेस "अनुबंध" तोड़ नहीं रहे हैं "यह संपत्ति कभी-कभी केवल पढ़ने के लिए होती है लेकिन कभी-कभी नहीं"? संभवतः आपको उन पाठों की अनुमति देने के लिए अपने इंटरफ़ेस को अलग करने की आवश्यकता है (उदाहरण के लिए, अन्य इंटरफ़ेस में), जिन्हें केवल पढ़ने और लिखने की आवश्यकता है। –

+0

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

+0

सहमत हैं, इंटरफ़ेस अनुबंध केवल निर्दिष्ट करते हैं कि आपको क्या कार्यान्वित करना है, न कि आप जो नहीं करते हैं। –

उत्तर

10

यह इस तरह से काम करता है क्योंकि गुण वास्तव में आभासी नहीं हैं - उनके एक्सेसर विधियां हैं। इस प्रकार, यदि आप बेस क्लास में कोई नहीं थे तो आप set को ओवरराइड नहीं कर सकते हैं।

आप क्या कर सकते हैं और छाया आधार वर्ग कार्यान्वयन ओवरराइड है, और अपने स्वयं के नए पढ़ने/लिखने के गुण प्रदान करते हैं।

class AbsClassB : AbsClass 
{ 
    public override double Top { get { return ((ConcClassB)this).Top } } 
    public override double Bottom { get { return ((ConcClassB)this).Bottom } } 
} 


class ConcClassB : AbsClassB 
{ 
    new public double Top 
    { 
     get { ... } 
     set { ... } 
    } 

    new public double Bottom 
    { 
     get { ... } 
     set { ... } 
    } 
} 

एक बेहतर विचार AbsClass में सही एक संरक्षित आभासी विधि को परिभाषित करने होंगे और के मामले में Top.get और Bottom.get लागू: मैं पदानुक्रम में एक अतिरिक्त वर्ग को शुरू करने के बिना यह करने के लिए किसी भी तरह से की पता नहीं है वह विधितो फिर तुम ConcClassB में सीधे उस विधि ओवरराइड कर सकते हैं, और गुण शैडो, एक अतिरिक्त वर्ग के लिए आवश्यकता के बिना:

abstract class AbsClass : IClass 
{ 
    public double Top 
    { 
     get { return GetTop(); } 
    } 

    public double Bottom 
    { 
     get { return GetBottom(); } 
    } 

    protected abstract double GetTop(); 

    protected abstract double GetBottom(); 
} 

class ConcClassB : AbsClass 
{ 
    new public double Top 
    { 
     get { ... } 
     set { ... } 
    } 

    new public double Bottom 
    { 
     get { ... } 
     set { ... } 
    } 

    protected override double GetTop() 
    { 
     return Top; 
    } 

    protected override double GetBottom() 
    { 
     return Bottom; 
    } 
} 
+0

लेकिन ConcClassB को AbsClass –

+0

से प्राप्त करने की आवश्यकता है, आपको इंटरफ़ेस को विस्तारित करने के लिए हमेशा एक सार परिभाषा का उपयोग करना चाहिए (यह घोषित करता है कि आप एक इंटरफ़ेस या समान के चर हैं) एक गंध है। आप या तो कंक्रीट वर्ग के तर्क/चर घोषित करने के साथ समाप्त होते हैं -> बुरा विचार अगर इसे इस मामले में टाला जा सकता है या आपको ठोस प्रकार के सीएनटी को कंक्रीट प्रकार में घोषित करने की आवश्यकता है नया ऑपरेशन उतना ही बुरा है क्योंकि आप लिस्कोव का उल्लंघन करेंगे। ऑपरेशन को प्रतिबंधित करना iis स्वीकार्य है जैसा कि E.g. के साथ किया जाता है। सूची जो IList (कोई टी) लागू नहीं करता है लेकिन "छुपाएं" (स्पष्ट कार्यान्वयन) कोई टाइप नहीं किया गया तरीका –

+0

हाँ, मेरी गलती - प्रश्न को गलत तरीके से पढ़ें। अद्यतन संस्करण देखें। –

0

मैं एक तरह से तुम क्यों सार्वजनिक सेटर तरीकों के लिए इन कार्यान्वयन कक्षाएं चाहेगा के रूप में उत्सुक हूँ कि सार्वजनिक इंटरफ़ेस का हिस्सा नहीं हैं। यह मुझे लगता है जैसे आप वास्तव में इन लोगों को जनता से अधिक प्रतिबंधित करना चाहते हैं?

इसके अलावा, मुझे इस दृष्टिकोण के साथ समस्या का सामना करने में कठिनाई हो रही है। वे सुपरक्लास से किसी भी गुण को "छुपाएं" करेंगे, लेकिन सुपरक्लास में कोई भी संपत्ति सेटर्स नहीं हैं, इसलिए यह ठीक लगता है। ऐसा लगता है कि यह सबसे आसान कामकाज हो सकता है।

+0

मैंने अपने प्रश्न के लिए जो कुछ भी कर रहा हूं उसके लिए मैंने एक संक्षिप्त सार व्याख्यान जोड़ा है। –

+0

यदि आप किसी ओवरराइड गेटर वाले किसी संपत्ति के लिए * निजी * सेटर जोड़ने का प्रयास करते हैं तो भी आप इस त्रुटि में भाग लेते हैं। – jwg

-13

एक वैश्विक चर का उपयोग करें।

संबंधित मुद्दे