2008-12-03 4 views
17

Bir "Uygulama" sınıfım olduğunu varsayalım. İlklendirilmek için kurucudaki belirli ayarları alır. Ayrıca, ayarların sayısının, kendilerine ait bir sınıfa yerleştirilmeye zorlanacağı kadar çok olduğunu varsayalım."Ortak" yuvalanmış sınıflar olsun ya da olmasın

Bu senaryoda aşağıdaki iki uygulamayı karşılaştırın.

Uygulama 1:

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

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

Uygulama 2: Bana göre

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

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

, ikinci yaklaşım çok tercih edilir. Daha okunabilir çünkü iki sınıf arasındaki ilişkiyi güçlü bir şekilde vurgular. Uygulama sınıfını herhangi bir yerde oluşturmak için kod yazarken, ikinci yaklaşım daha güzel görünecek.

Şimdi sadece Ayarlar sınıfının kendisinin de benzer şekilde "ilgili" bir sınıfı olduğunu ve bu sınıfın da bunu yaptığını hayal edin. Yalnızca bu tür üç seviyeye geçin ve 'yuvalanmayan' durumda sınıf adlandırma elden çıkar. Bununla birlikte, yuva yaparsanız, işler hala zarif kalır.

Yukarıdakilere rağmen, StackOverflow üzerinde iç içe geçmiş sınıfların yalnızca dış dünya tarafından görülemiyorsa haklı olduğunu söyleyen insanları okudum; eğer sadece sınıfın içsel uygulaması için kullanılıyorlarsa. Yaygın olarak anılan itiraz, sınıfın kaynak dosyasını içeren boyutun şişirilmesidir, ancak kısmi sınıflar bu sorun için mükemmel bir çözümdür.

Benim sorum şu, neden iç içe geçmiş sınıfların "kamuya açık" kullanımı konusunda ihtiyatlıyız? Bu kullanıma karşı başka argümanlar var mı?

cevap

22

Sanırım sorun yok. Bu temel olarak yapımcı modelidir ve yuvalanmış sınıfları kullanmak oldukça iyi çalışır. Ayrıca, kurucunun dış sınıfın özel üyelerine erişmesine izin verir, bu da çok kullanışlı olabilir. Örneğin, oluşturucu bir örneğini alır dış sınıfına özel yapıcısını çağırır oluşturucu bir Yapı yöntemi olabilir: sağlar

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

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

olduğu bir örneğini binanın sadece yolu dış sınıf oluşturucu ile.

C# numaralı Protokol Arabellekleri bağlantısında böyle bir şablon kullanıyorum.

+0

Son zamanlarda bazı kurucu kodu yazmalı ve bu yazıyı hatırladım. Çok kullanışlı bir yaklaşım olduğu ortaya çıktı, teşekkürler. –

+0

* Sadece açık bir atıfta bulunularak * "Aynı zamanda dış sınıfının oluşturucu erişim özel üyeleri sağlayan" (I Java'nın iç sınıflarında Olduğu gibi bu örtülü değil eminim) doğru ?. – samosaris

+0

@SamusArin: Evet, içeren sınıfın bir örneğine örtük bir başvuru yoktur. Ama ayrıca statik üyelere de erişebilirsiniz. Temelde sadece * erişilebilirlik hakkında konuşuyordum. –

0

Konuyla ilgili Microsoft has to say nolu sayfaya bakmak isteyebilirsiniz. Temelde söyleyeceğim bir stil meselesi.

+0

.NET, Java gibi "tek (kamu) sınıf dosya başına" kuralını empoze etmez. Yapısını programlamak için farklı paradigmalara sahipler. Bu kuralı tek başına WRT, .NET'in daha fazla esnekliği var (eğer yapacaksanız etkileyici bir süper set). Büyük makale btw. – samosaris

0

İç içe geçmiş ve/veya kapsayıcı sınıfına ince ayar erişimi için öncelikle yuvalanmış sınıflar kullanıyorum. Unutulmaması gereken bir şey, yuvalanmış bir sınıf tanımının temel olarak bir sınıf üyesi olması ve tüm muhafazanın özel değişkenlerine erişimi olacaktır.

Bunu, belirli bir sınıfın kullanımını denetlemek için de kullanabilirsiniz.

Örnek: o dış uygulaması halinde

public abstract class Outer 
{ 
    protected class Inner 
    { 
    } 
} 

Şimdi, bu durumda, (sınıfınızın) kullanıcı sadece, İç sınıfa erişebilirsiniz.

+1

Iff bir yazım hatası olmayabilir, ancak * zaten * "cümle" kelimesine sahip olduğunuzdan biraz fazladır. – phoog

5

İlgili alanları ilişkilendirmek için ad alanlarını kullanabilirsiniz. Örneğin

:

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

    public class Filling { } 
} 
onlar ad sanki sınıfları kullanarak üzerinden bu avantajı isteğe şeyleri kısaltmak için çağrı tarafında using kullanabilirsiniz olmasıdır

:

using Diner; 

... 

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

Eğer Sandwich sınıfını, Filling için bir ad alanıymış gibi kullanın, Sandwich.Filling tam adını kullanmak için Filling'a başvurmanız gerekir.

Ve bunu bilerek geceleri nasıl uyuyacaksınız?

+2

Ad alanları tercihine katılıyorum, ancak bazen işe yaramıyorlar. Söz konusu örnekte, örneğin, 'Uygulama' terimi 'Ayarlar' altını çizer, ancak her ikisini de ortak bir ad alanına koymak, bu anlamı taşımamaktadır. –

+0

** 'Doldurma = Diner.Filling kullanarak' '** bir 'namespace olarak sınıflar' durumunda (sadece) **' Dolgu '**' nun referanslarını çözmelidir. – samosaris

0

Genel yuvalanmış sınıfların geçerli kullanımı için sahip olduğum başka bir pratik örnek, IEnumerable özelliğine sahip bir viewmodel kullandığımda MVC düzenindedir. Örneğin: Ben içerdiği yalnızca o belirli ViewModel için özelleştirilmiş olduğu için Product sınıf dışında yeniden kullanılacak istemiyorum çünkü

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; } 
} 

} 

ben kullanıyorum. Ama bunu özel yapamıyorum çünkü Ürünler mülkiyeti kamuya ait.