2008-12-03 93 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 
    } 
} 

對我來說,第二種方法是非常優選的。它更具可讀性,因爲它強調兩類之間的關係。當我編寫代碼來實例化Application類時,第二種方法將看起來更漂亮。

現在想象一下Settings類本身又有一些類似的「相關」類,而這個類反過來也是如此。只有三個這樣的級別,並且在「非嵌套」情況下,類命名將失去控制。但是,如果你築巢,事情仍然保持優雅。

儘管如上所述,我已經閱讀過有人在StackOverflow上說過,只有當外部世界不可見時,嵌套類纔是合理的;也就是說,如果它們僅用於包含類的內部實現。通常引用的反對意見是膨脹了包含類的源文件的大小,但部分類是這個問題的完美解決方案。

我的問題是,爲什麼我們要警惕「公開暴露」使用嵌套類?還有其他反對這種用法的論據嗎?

回答

22

我覺得很好。這基本上是構建器模式,使用嵌套類工作得很好。它還允許構建器訪問外部類的私有成員,這可能非常有用。例如,你可以對生成器生成方法,它調用的外部類私有構造這需要建設者的一個實例:

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

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

這保證了建設的一個實例的唯一方式外部類是通過建設者。

我在Protocol Buffers的C#端口中使用了非常像這樣的模式。

+0

我最近不得不寫一些builder代碼,並記得這篇文章。原來這是一個非常有用的方法,所以謝謝。 – 2010-06-12 13:33:53

+0

*「它也讓構建者訪問外部類的私有成員」*只有明確的引用,正確(我敢肯定它不像Java的內部類中那樣是隱含的)。 – samosaris 2017-06-19 17:44:15

0

您可能想查看關於該主題的什麼Microsoft has to say。基本上這是一個我會說的風格問題。

+0

.NET不強加Java所做的「每個文件一個(公共)類」規則。他們似乎對程序結構有着截然不同的範例。 WRT只有這一條規則,.NET具有更大的靈活性(如果你願意的話,它是一個富有表現力的超級集合)。偉大的文章btw。 – samosaris 2017-06-19 19:38:48

0

我主要使用嵌套類來微調對嵌套和/或容器類的訪問。

要記住的一件事是,嵌套類定義基本上是一個類成員,並且將有權訪問所有容器的私有變量。

您也可以使用它來控制特定類的使用情況。

例子:

public abstract class Outer 
{ 
    protected class Inner 
    { 
    } 
} 

現在,在這種情況下,(類)的用戶只能訪問內部類,如果他實現外。

+1

Iff可能不是拼寫錯誤,但它*有點多餘,因爲您在句子中已經有單詞「only」。 – phoog 2015-12-21 15:29:30

5

您可以使用命名空間來關聯...相關的事物。

例如:

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

    public class Filling { } 
} 

的這種過度使用類,好像他們是命名空間的好處是,你可以選擇使用using主叫方縮寫事情:

using Diner; 

... 

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

如果您使用Sandwich類就好像它是Filling的名稱空間一樣,必須使用全名Sandwich.Filling來指代Filling

你知道那個晚上怎麼睡覺?

0

另一個我有效使用公共嵌套類的實際例子是MVC模式,當我使用IEnumerable屬性使用viewmodel。例如:

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類,因爲它僅包含其特定視圖模型定製重複使用外也。但是由於產品屬性是公開的,所以我不能將它變爲私有。