2008-12-03 15 views
17

मान लीजिए कि मेरे पास कक्षा 'एप्लिकेशन' है। आरंभ करने के लिए यह कन्स्ट्रक्टर में कुछ सेटिंग्स लेता है। आइए यह भी मान लें कि सेटिंग्स की संख्या इतनी है कि यह उन्हें स्वयं की कक्षा में रखने के लिए मजबूर है।"सार्वजनिक" नेस्टेड कक्षाएं या

इस परिदृश्य के निम्नलिखित दो कार्यान्वयन की तुलना करें।

कार्यान्वयन 1:

class Application 
{ 
    Application(ApplicationSettings settings) 
    { 
     //Do initialisation here 
    } 
} 

class ApplicationSettings 
{ 
    //Settings related methods and properties here 
} 

कार्यान्वयन 2:

class Application 
{ 
    Application(Application.Settings settings) 
    { 
     //Do initialisation here 
    } 

    class Settings 
    { 
     //Settings related methods and properties here 
    } 
} 
मेरे लिए

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

अब कल्पना करें कि सेटिंग क्लास में कुछ समान रूप से "संबंधित" वर्ग था और उस वर्ग ने भी बदले में ऐसा किया था। केवल तीन ऐसे स्तरों पर जाएं और कक्षा नामकरण 'गैर-नेस्टेड' मामले में हाथ से बाहर हो जाता है। यदि आप घोंसला करते हैं, हालांकि, चीजें अभी भी सुरुचिपूर्ण रहती हैं।

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

मेरा सवाल है, हम नेस्टेड कक्षाओं के "सार्वजनिक रूप से उजागर" उपयोग से क्यों सावधान हैं? क्या इस तरह के उपयोग के खिलाफ कोई अन्य तर्क हैं?

उत्तर

22

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

public class Outer 
{ 
    private Outer(Builder builder) 
    { 
     // Copy stuff 
    } 

    public class Builder 
    { 
     public Outer Build() 
     { 
      return new Outer(this); 
     } 
    } 
} 

कि सुनिश्चित करता है कि केवल का एक उदाहरण के निर्माण के रास्ते बाहरी वर्ग बिल्डर के माध्यम से है।

मैं प्रोटोकॉल बफर के अपने सी # पोर्ट में इस तरह के एक पैटर्न का उपयोग करता हूं।

+0

मुझे हाल ही में कुछ बिल्डर कोड लिखना पड़ा और इस पोस्ट को याद किया। यह एक बहुत ही उपयोगी दृष्टिकोण साबित हुआ, इसलिए धन्यवाद। –

+0

* "यह निर्माता को बाहरी वर्ग के निजी सदस्यों तक पहुंचने देता है" * केवल एक स्पष्ट संदर्भ के साथ, सही (मुझे पूरा यकीन है कि यह जावा की आंतरिक कक्षाओं में निहित नहीं है)? – samosaris

+0

@ सैमसएरिन: हां, युक्त कक्षा के उदाहरण के लिए कोई अंतर्निहित संदर्भ नहीं है। लेकिन आपके पास स्थिर सदस्यों तक पहुंच है। असल में मैं * केवल * पहुंच के बारे में बात कर रहा था। –

0

आप इस विषय पर Microsoft has to say देख सकते हैं। असल में यह शैली का सवाल है जो मैं कहूंगा।

+0

.NET "एक (सार्वजनिक) कक्षा प्रति फ़ाइल" नियम लागू नहीं करता है जो जावा करता है। ऐसा लगता है कि कार्यक्रम संरचना के लिए अलग-अलग प्रतिमान हैं। डब्लूआरटी अकेले यह एक नियम है, .NET में अधिक लचीलापन है (यदि आप करेंगे तो एक अभिव्यक्तिपूर्ण सुपर-सेट)। महान लेख बीटीडब्ल्यू। – samosaris

0

मैं मुख्य रूप से नेस्टेड और/या कंटेनर कक्षा में ठीक-ट्यूनिंग पहुंच के लिए नेस्टेड कक्षाओं का उपयोग करता हूं।

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

आप इसका उपयोग किसी विशिष्ट वर्ग के उपयोग को नियंत्रित करने के लिए भी कर सकते हैं।

उदाहरण:

public abstract class Outer 
{ 
    protected class Inner 
    { 
    } 
} 

अब, इस मामले में, (अपने वर्ग के) उपयोगकर्ता केवल इनर वर्ग, उपयोग कर सकते हैं अगर वह बाहरी लागू करता है।

+1

Iff एक टाइपो नहीं हो सकता है, लेकिन यह * कुछ हद तक अनावश्यक है क्योंकि आपके पास पहले से ही वाक्य में "केवल" शब्द है। – phoog

5

आप संबंधित चीज़ों से संबंधित चीज़ों को संबंधित करने के लिए नामस्थान का उपयोग कर सकते हैं ... संबंधित।

उदाहरण के लिए:

namespace Diner 
{ 
    public class Sandwich 
    { 
     public Sandwich(Filling filling) { } 
    } 

    public class Filling { } 
} 

वर्गों का उपयोग करना रूप में यदि वे नामस्थान थे पर इस का लाभ यह है कि आप वैकल्पिक रूप से बुला तरफ using उपयोग कर सकते हैं चीजों को संक्षिप्त करने के लिए है:

using Diner; 

... 

var sandwich = new Sandwich(new Filling()); 

आप तो Sandwich कक्षा का उपयोग करें जैसे कि यह Filling के लिए नामस्थान था, तो आपको Filling का संदर्भ देने के लिए पूर्ण नाम Sandwich.Filling का उपयोग करना होगा।

और रात में आप कैसे सो रहे हैं यह जानकर?

+2

मैं नामस्थानों के लिए वरीयता से सहमत हूं, लेकिन कभी-कभी वे काफी काम नहीं करते हैं। उदाहरण के लिए, उदाहरण के लिए, अर्थात् 'एप्लिकेशन' 'सेटिंग्स' को कम करता है, लेकिन उन्हें एक सामान्य नामस्थान में रखने के लिए उस अर्थ को व्यक्त नहीं किया जाएगा। –

+0

** 'भरने का उपयोग = डिनर। भरना; '** को" नामस्थान के रूप में कक्षाओं "के मामले में ** (') भरना ** ** भरना चाहिए। – samosaris

0

सार्वजनिक घोंसला वाले वर्गों के वैध उपयोग के लिए मेरे पास एक और व्यावहारिक उदाहरण है जो एमवीसी पैटर्न में है जब मैं एक आईनेमरेबल संपत्ति के साथ व्यूमोडेल का उपयोग करता हूं। उदाहरण के लिए:

public class OrderViewModel 
{ 
public int OrderId{ get; set; } 
public IEnumerable<Product> Products{ get; set; } 

public class Product { 
public string ProductName{ get; set; } 
public decimal ProductPrice{ get; set; } 
} 

} 

मैं इसका इस्तेमाल क्योंकि मैं करने के लिए Product कक्षा के बाहर फिर से इस्तेमाल किया जा है क्योंकि यह केवल कि विशिष्ट viewmodel जो उसमें शामिल के लिए अनुकूलित है नहीं करना चाहती। लेकिन मैं इसे निजी नहीं बना सकता क्योंकि उत्पाद संपत्ति सार्वजनिक है।

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