2009-04-09 16 views
6

मैं सी # 2.0 में काम कर रहा हूं, लेकिन यह अधिकांश ऑब्जेक्ट उन्मुख भाषाओं पर लागू होगा। जब मैं निजी क्षेत्रों को लपेटने वाले सार्वजनिक गुणों के साथ कक्षाएं बनाता हूं, तो मैं & पर वापस स्विच करता हूं कि मुझे आंतरिक रूप से संपत्ति या क्षेत्र का उपयोग करना चाहिए या नहीं। बेशक सी # 3.0 ऑटो-गुणों के साथ यह आसान बनाता है, लेकिन यह अभी भी लागू हो सकता है।ओओ डिजाइन - क्या आप आंतरिक संपत्तियों या निजी क्षेत्रों का आंतरिक रूप से उपयोग करते हैं?

क्या इससे कोई फर्क पड़ता है?

public class Person 
{ 
    private string _name = ""; 

    public string Name 
    { 
     get { return _name; } 
     set { _name = value; } 
    } 

    public Person(string name) 
    { 
     _name = name; //should I use the property or field here? 
    } 
} 

उत्तर

2

ज्यादातर यह एक कोड वरीयता तरह है, लेकिन मैं 'सार्वजनिक गुण या कभी निजी संपत्तियों का उपयोग करना पसंद, तो आप बस कुछ तर्क संपत्ति के लिए फोन करने वाले कोड में बिना किसी परिवर्तन के जोड़ सकते हैं। 3.5 .NET में भी आपके पास ऑटोप्रोपर्टी के रूप में उपयोगी कोड चीनी है।

2

मैं संपत्ति का उपयोग कर की सिफारिश करेंगे, आपको कभी पता नहीं है जब आप अपनी संपत्ति यानी अंदर कुछ कर किया जा रहा है हो सकता है। आलसी लोडिंग, रूपांतरण, स्वरूपण, गणना आदि। यदि आप निजी सदस्य का उपयोग करते हैं तो एक बग पेश करेंगे ...

0

आम तौर पर मैं कुछ अपवादों के साथ सार्वजनिक गुणों का उपयोग करता हूं जहां मैं किसी भी अतिरिक्त कोड से बचने के लिए कह सकता हूं संपत्ति एक्सेसर। सी # 3.0 में स्वचालित गुणों के साथ मैं शायद ही कभी हाथ से बैकिंग फ़ील्ड बना देता हूं; आमतौर पर केवल जब स्वचालित बैकिंग फ़ील्ड का डिफ़ॉल्ट मान मेरी संपत्ति के लिए उपयुक्त नहीं है।

0

कम से कम जावा में, वहाँ कोई तरीका है कि आप सार्वजनिक क्षेत्रों का उपयोग होता है क्योंकि अच्छे पुराने JavaBeans सम्मेलनों, कि हर कोई उपयोग करने के लिए लगता है। मुझे लगता है कि सी # गुणों की पहली भाषा संरचना है। मैं उस

+1

हां यह करता है, सी # का एक बड़ा लाभ। – Randolpho

+0

हम उन लोगों के लिए क्या बात कर रहे हैं जो इन जवाबीनर चीज़ों को नहीं जानते हैं? –

+1

आपको सम्मेलनों का पालन नहीं करना चाहिए क्योंकि "हर कोई उनका उपयोग करता है," विशेष रूप से यदि आप इसे स्वयं को उचित नहीं ठहरा सकते हैं। सम्मेलन का मतलब यह नहीं है कि यह एक अच्छा विचार है। सवाल करो! :) – JoshJordan

0

आपको "नाम" (संपत्ति) का उपयोग करना चाहिए, क्योंकि यदि आप इस मूल्य के लिए कुछ चेक चाहते हैं, तो आप इसे "नाम" संपत्ति के सेटटर में रख सकते हैं और फिर हाल ही में निर्माता के लिए उपयोग किया जाएगा सेटिंग मूल्य भी।

1

संपत्ति का उपयोग करें। या बेहतर अभी तक, अगर आप सी # 3.0 या तो की तरह ऊपर उपयोग स्वत: गुण का उपयोग कर रहे:

public class Person 
{ 
    public string Name { get; set; } 

    public Person(string name) 
    { 
     Name = name; //should I use the property or field here? 
    } 
} 

आप संपत्ति का उपयोग करते हैं अब आप स्वत: गुण का उपयोग करने के लिए अपने कोड को संशोधित तैयार हो जाएंगे।

14

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

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

दूसरी ओर, निर्माता संभवतः, इस के लिए एक अपवाद हो सकता है क्योंकि आप प्रारंभिक मूल्यों को निर्धारित कर सकते हैं।

लेकिन सामान्य तौर पर, मैं संपत्ति के माध्यम से पहुँच कहेंगे।

संपादित

ए (तुच्छ/काल्पनिक) उदाहरण

public class Person 
{ 
    private string _name = ""; 
    private List<String> oldnames = new ArrayList(); 

    public string Name 
    { 
     get { return _name; } 
     set 
     { 
      oldnames.Add(_name); 
      _name = value; 
     } 
    } 

    public Person(string name) 
    { 
     _name = name; //should I use the property or field here? 
    } 
} 

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

+0

मुझे लगता है कि मुझे यह इंगित करना चाहिए कि जावा और सी # अलग-अलग भाषाएं हैं। सी # गुण है, जावा नहीं है। – epochwolf

+0

इस प्रतिक्रिया को शामिल करने के लिए मैं अपना उत्तर कैसे संपादित कर सकता हूं? – DevinB

+0

ओह, मैं देखता हूं, हाँ किसी कारण से मैंने सोचा कि सवाल जावा से संबंधित था। – DevinB

0

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

हालांकि, ऐसे समय भी होंगे जब आपको उस प्रीप्रोकैसिंग तर्क को रोकने की आवश्यकता होगी। असल में, मैंने कई बार देखा है जब डेवलपर्स अनजाने में निजी क्षेत्र की बजाय सार्वजनिक संपत्ति का उपयोग करके अनंत लूप बनाते हैं (माफ के शीर्ष से एक उदाहरण के बारे में नहीं सोच सकते हैं)।

लिंक से SQL उत्पन्न कक्षाएं एक अच्छा उदाहरण हैं, मुझे लगता है, क्योंकि वे दिखाते हैं कि संपत्ति में कितना तर्क मौजूद हो सकता है। कुछ विस्तार विधियों को लिखने का प्रयास करें और आप अंतर को समझना शुरू कर देंगे।

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

1

ऐसी स्थिति हो सकती है जब आपको आंतरिक रूप से क्षेत्र तक पहुंच प्राप्त हो। उदाहरण के लिए, जब आप केवल सार्वजनिक रूप से केवल संपत्ति के लिए केवल पढ़ने की पहुंच प्रदान करते हैं और किसी ऑब्जेक्ट को तत्काल करने के बाद बदलने की अनुमति नहीं दी जाती है।

public class MyClass 
{ 
    private string _MyProperty; 

    public MyProperty { get { return _MyProperty; } } 

    public MyClass() 
    { 
     _MyProperty = SomeVeryComplexPropertyInitializationLogic(); 
    } 
} 
1

यदि आप फ़ील्ड नाम का उपयोग करते हैं, तो आपको encapsulation नहीं मिलता है। Encapsulation न केवल वर्गों के बीच, बल्कि एक वर्ग के भीतर लागू होता है।

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

लें (हालांकि ढांचा इस समस्या को कष्ट नहीं होता है, मैं बस यह उपयोग कर रहा हूँ उदाहरण देकर स्पष्ट करना):

मान लीजिए कि यह थे चलो मूल वर्ग:

class RadioChoice { 
    private String prefix; 

    RadioChoice(String prefix) { 
    this.prefix = prefix ; 

    setPrefix(String prefix) { 
    this.prefix = prefix ; 
    } 
} 

यहाँ हम पहले से ही एक समस्या देख सकते हैं: एक ही आपरेशन this.prefix = prefix टो स्थानों में होता है। यह बिल्कुल वही काम करने के लिए है, लेकिन चूंकि यह दो स्थानों पर होता है, इसलिए "एक ही चीज़" दो अलग-अलग चीजों में अलग हो सकती है। (इसे डेटाबेस सामान्यीकरण के लिए तुलना करें, एक अभ्यास जिसे ठीक से रोकने के लिए डिज़ाइन किया गया है।)

अब, अपाचे विकेट में वेब पृष्ठों को प्रस्तुत करने के तरीके में परिवर्तन रिकॉर्ड करने की अवधारणा है, ताकि उन परिवर्तनों को पूर्ववत किया जा सके। यह "पूर्ववत करें" ऑब्जेक्ट की एक सूची संग्रहीत करके करता है। एक RadioChoice के उपसर्ग उन चीजों है कि पूर्ववत किया जा सकता से एक है, और इसलिए 'उपसर्ग' सेटर परिवर्तन रिकॉर्ड करना होगा:

class RadioChoice { 
    private String prefix; 

    RadioChoice(String prefix) { 
    this.prefix = prefix ; 

    setPrefix(String prefix) { 
    // save the old prefix 
    this.getPage().addChange(new PrefixChange(this.prefix)); 
    // set the new one 
    this.prefix = prefix ; 
    } 
} 

अब देखो क्या होता है: क्योंकि निर्माता उपसर्ग सीधे सेट, कोई परिवर्तन नहीं से सहेजा जाता है सीटीओआर अगर हमने सेटर का इस्तेमाल किया होता, तो सीटीआर रीफैक्टरिंग के बाद स्वचालित रूप से "सही काम करेगा"। इसके बजाय, हमें दोनों सेटर और सीटीओआर को दोबारा रिफैक्टर करना होगा।

बेशक

, हमारे कोड अभी भी इष्टतम से कम है, वास्तव में यह इस होना चाहिए:

setPrefix(String prefix) { 
    // save the old prefix 
    this.getPage().addChange(new PrefixChange(this.getPrefix())); 
    // set the new one 
    this.prefix = prefix ; 
    } 
} 

स्कॉट Meyers (इस पर लेख, जहां वह वकालत की कि की एक श्रृंखला था C++, जिसमें नि: शुल्क कार्य हैं) एक वर्ग का खुलासा करता है केवल आदिम कार्यों (आदिम कार्यों: कक्षाएं iteslf को छोड़कर संभव नहीं है) और यह कि सभी कार्यों को प्राथमिक कार्यों से बनाया जा सकता है, उन्हें नि: शुल्क कार्य किया जा सकता है। यह एक दुबला इंटरफेस, अधिक स्थिर इंटरफेस के लिए बनाता है।

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

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