2010-01-08 11 views
9

विरासत कक्षाओं में स्थिरांक या अन्य क्षेत्रों को शुरू करने का सबसे अच्छा तरीका क्या है? मुझे एहसास है कि इस उदाहरण में कई वाक्यविन्यास त्रुटियां हैं, लेकिन यह स्पष्ट करने के लिए यह सबसे अच्छा उदाहरण है कि मैं क्या करने की कोशिश कर रहा हूं।विरासत कक्षाओं में फ़ील्ड शुरू करना

public abstract class Animal { 
    public abstract const string Name; // #1 
    public abstract const bool CanFly; 
    public abstract double Price; // price is not const, because it can be modified 

    public void Fly() { 
    if (!CanFly) 
     Debug.Writeln("{0}s can't fly.", Name); 
    else 
     Debug.Writeln("The {0} flew.", Name); 
    } 
} 

public class Dog : Animal { 
    public override const string Name = "Dog"; // #2 
    public override const bool CanFly = false; 
    public override double Price = 320.0; 
} 

public class Bird : Animal { 
    public override const string Name = "Bird"; 
    public override const bool CanFly = true; 
    public override double Price = 43.0; 
} 
कुछ बातें मैं पूरा करने के लिए कोशिश कर रहा हूँ

:

  • बेस कक्षाएं इन 3 क्षेत्रों सौंपनी होगी।
  • आदर्श रूप में मैं चाहता हूं कि ये प्रारंभिक फ़ील्ड कक्षा के शीर्ष पर एक साथ रहें ताकि मैं देख सकूं कि प्रत्येक वर्ग को कौन सा स्थिरांक सौंपा गया है और जब भी आवश्यक हो उन्हें बदल दें।
  • फ़ील्ड का नाम और कैनफ़ाई बदला नहीं जा सकता है।

मुझे पता है कि आप इन क्षेत्रों को एक कन्स्ट्रक्टर (यदि आप कॉन्स से छुटकारा पाएं) में प्रारंभ कर सकते हैं, लेकिन फिर उन्हें असाइन करने की गारंटी नहीं है। यदि आपके पास इन फ़ील्ड्स के गुण हैं और उन्हें ओवरराइड करते हैं, तो आपको अभी भी संपत्ति के बैकिंग फ़ील्ड को प्रारंभ करना होगा। आप इसे कैसे कार्यान्वित करेंगे?

कुछ वाक्यविन्यास त्रुटियों इसके बारे में शिकायत:

  • संशोधक 'सार' खेतों पर मान्य नहीं है। इसके बजाय एक संपत्ति का उपयोग करने का प्रयास करें। (# 1)
  • एक स्थिरांक क्षेत्र उपलब्ध कराई जाने वाली एक मूल्य की आवश्यकता है (# 1)
  • संशोधक 'ओवरराइड' मान्य नहीं है इस आइटम के लिए है (# 2)
+3

मुझे लगता है कि आप समझ रहे हैं कि स्थिरांक क्या हैं। Constants उन मानों के लिए हैं जो ब्रह्मांड के पूरे इतिहास में कभी नहीं बदलते; इसलिए, नाम "स्थिर" है। स्थिरांक के अच्छे उदाहरण: एक दर्जन में अंडों की संख्या, परमाणु संख्या की लीड। खराब: आपके आवेदन की संस्करण संख्या; समय के साथ यह परिवर्तन। भयानक: तेल की एक बैरल की कीमत; हर कुछ सेकंड में बदलता है। यदि कोई ऐसा क्षेत्र है जिसका मूल्य आपके आवेदन के जीवनकाल के दौरान बदल सकता है, तो यह निरंतर नहीं है। स्पष्टीकरण के लिए –

+0

धन्यवाद। मुझे लगता है कि मैं थोड़ी उलझन में था क्योंकि कुत्ता। नाम और कुत्ता। कैनफली फ़ील्ड कभी नहीं बदला जाना चाहिए, इस प्रकार मुझे लगता है कि उन्हें स्थिरांक होना चाहिए। हालांकि, Animal.Name और Animal.CanFly फ़ील्ड विरासत कक्षाओं द्वारा बदला जाएगा, इसलिए उन्हें स्थिरांक नहीं होना चाहिए। मैं उन्हें विरासत में केवल कक्षाओं में स्थिरांक के रूप में परिभाषित करने की कोशिश कर रहा था, जो मुझे लगता है कि आप नहीं कर सकते हैं। – Senseful

+0

निर्माण मूल्य पर एक बार सेट किए गए मान को मॉडल करने के लिए और इसके बाद कभी नहीं बदला गया, एक पठनीय क्षेत्र का उपयोग करें। रीडोनली फ़ील्ड्स उदाहरण फ़ील्ड हो सकते हैं, इस मामले में आप प्रत्येक इंस्टेंस या स्थिर के लिए एक अलग मूल्य प्राप्त कर सकते हैं, इस मामले में प्रत्येक इंस्टेंस एक ही मान साझा करता है। –

उत्तर

19

एक आधार वर्ग एक व्युत्पन्न वर्ग द्वारा उपलब्ध कराई जाएगी एक मूल्य की आवश्यकता है, दो सबसे आम तरीके हैं:

निर्माता में यह आवश्यक है:

public readonly double Price; 

protected BaseClass(double price) 
{ 
    this.Price = price; 
} 

व्युत्पन्न वर्गों निर्माता में कीमत से गुजरना होगा:

public Derived() : base(32) 
{ 
} 

या, बनाने यह एक अमूर्त संपत्ति:

public abstract double Price { get; } 

व्युत्पन्न वर्गों मान देने के लिए किसी तरह प्रदान करनी चाहिए (हालांकि वे कहाँ मिलता है यह व्युत्पन्न वर्ग है, जो कई मामलों में अधिक लचीलापन प्रदान करता पर निर्भर है):

public override double Price 
{ 
    get 
    { 
     return 32; 
    } 
} 
+1

एक अमूर्त संपत्ति का संभावित नुकसान यह है कि व्युत्पन्न कक्षाएं "जीवनकाल के दौरान कभी भी परिवर्तन नहीं" तोड़ सकती हैं, जिसे रीडोनली फ़ील्ड + सीटीओआर के साथ लागू किया जा सकता है। –

5

आप विशेष करना चाहते हैं अपने अमूर्त वर्ग में खेतों, लेकिन उन्हें बेस क्लास में परिभाषित नहीं करना चाहते हैं, आप आवश्यकता हो सकती है कि कार्यान्वयनकर्ता कन्स्ट्रक्टर के माध्यम से मूल्यों की आपूर्ति करें।

public abstract class MyClass 
{ 
    private readonly double price; 

    protected MyClass(double price) 
    { 
     this.price = price 
    } 
} 
इस तरह के एक आधार वर्ग के साथ

, सभी व्युत्पन्न वर्ग चाहिए आधार वर्ग 'निर्माता के लिए एक मूल्य की आपूर्ति, या कोड संकलन नहीं होंगे। यहाँ लग सकता है कि कैसे में से एक उदाहरण है:

public class Foo : MyClass 
{ 
    public Foo() : base(42) { } 
} 
1

आप इस व्यवहार को लागू करने के लिए readonly और internal कन्स्ट्रक्टर का उपयोग कर सकते हैं लेकिन यह कुछ हद तक खत्म हो जाएगा।यदि आप इसके साथ जाते हैं तो आंतरिक कन्स्ट्रक्टर का लाभ उठाने के लिए विरासतकर्ताओं को एक ही नामस्थान/असेंबली में होना आवश्यक होगा।

0

दूसरा मॉडल आभासी है जो एक एक्सेसर (संपत्ति) बनाना है। यह व्युत्पन्न कक्षाओं को लागू करने के लिए मजबूर करता है।

इसका लाभ यह है कि 'कैनफ्लाई' का उत्तर हो सकता है जो दिन के समय (कहने) पर निर्भर करता है।

1

आपको जो त्रुटियां मिलती हैं, वे आपको कम से कम बताती हैं कि क्या करना है। आप Name और CanFly के लिए, अमूर्त गुणों का उपयोग नहीं करना चाहते हैं, जबकि Price एक सामान्य संपत्ति होगी। व्युत्पन्न कक्षाओं में, अमूर्त गुण केवल पढ़ने के लिए और प्रत्येक मामले में निरंतर वापस आ जाएंगे। कोड में:

public abstract class Animal { 
    public abstract string Name { get; } 
    public abstract bool CanFly { get; } 
    public double Price { get; set; } 
    // etc 
} 

public class Dog : Animal { 
    public override string Name { get { return "Dog"; } } 
    public override bool CanFly { get { return false; } } 
    public Dog() { Price = 320.0; } 
} 

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