2013-03-03 33 views
2

在我的自我努力中,我將編程技能和習慣帶入了21世紀(從Pascal & Fortran遷移到C#和C++),我一直在研究大量可用的源代碼。就我所能確定的,類是獨特的「獨立」實體(很像它們的函數祖先)。在C#和C++中使用嵌套類 - 爲什麼和何時?

但是,我有很多實例,其中一個或多個類嵌套在另一個類中。在這方面,我的「直覺本能」是這樣做的,僅僅是由於極其糟糕的方法論 - 然而,我還不熟悉現代面向對象方法來真正做出這樣的決定。

因此,下面的重疊問題:

是否有嵌套內另一個類合法的理由?而且,如果是這樣,這樣做的理由是什麼,而不是每個階層完全獨立?

(注:我已經看到了一直在使用C#的例子,但似乎這方面同樣適用於C++)

+0

它們可以用於泛型類,這樣泛型類的每個「版本」都會有與之相關的不同類型(即:'Generic 。嵌套'與'Generic 。嵌套'不同。 – antonijn 2013-03-03 20:17:48

+0

@Antonijn不能解釋它爲什麼嵌套。爲什麼不'通用'和'嵌套'? – 2013-03-03 20:20:58

+1

當然可以有一個合法的理由。這裏是.NET的BCL的一個例子。公共類[AdjustmentRule](http://msdn.microsoft.com/en-us/library/system.timezoneinfo.adjustmentrule)嵌套在公共類[System.TimeZoneInfo](http://msdn.microsoft.com /en-us/library/system.timezoneinfo)。原因是_調整規則_是一種「從屬」_時區信息_。另一個例子是當一個嵌套的'private'類存在於另一個類中時。這可能是因爲內部類只是作爲包含類的一種實現細節而需要。 – 2013-03-03 20:22:02

回答

3

嗯,這可能要求一個非常暗示的答案,因此很多人會不同意我的回答。我是這些人誰相信有嵌套類沒有真正的需要之一,我經常會用你的聲明同意:

在這方面,我的「本能」的是,這樣做只是由於極度貧窮的方法

案例,人們覺得有必要設計嵌套類是其中的功能,是緊耦合的外部類設計的行爲。例如。事件處理可以設計在內部類中,或者行爲可以找到內部類的方式。

我寧願重構「外部」類中的特定行爲,以便最終得到兩個具有明確責任的較小類。

對我來說,設計內部類的主要缺點是它們傾向於雜亂的功能,很難與主體一起使用,如TDD(測試驅動開發)。

如果你不依賴於測試主體,我認爲它不會對你造成很大的傷害。它(像很多事情一樣)是一種品味的問題,而不是正確或錯誤的問題。我瞭解到這個話題會導致討論冗長而耗時。與你是否應該使用static助手類非常相似,這些助手類往往不僅僅是「成爲助手」,而且隨着時間的推移越來越多。

如果您遇到真實生活的例子,討論可以變得更具體。在此之前,它將主要是人們的「直覺」。

0

你經常遇到嵌套類的一個領域(儘管可能沒有注意到)是枚舉器(即實現IEnumerator<T>的類)。

爲了使集合支持多個同時枚舉(例如,在多個線程上,或者甚至只是在同一個集合上嵌套循環),枚舉邏輯需要從集合中分離到另一個類中。

但是,爲了正確工作,枚舉器通常需要具體的集合實現細節知識。如果你是用一個完全獨立的(非嵌套的)類來做到這一點,那麼你就必須讓內部更容易被訪問,從而破壞封裝。 (也許有人可能會爭辯說可以使用internal成員來完成,但我認爲這仍然會在某種程度上破壞封裝,即使它只是「向實現細節向同一個程序集的成員公開)。

通過爲枚舉器使用私有嵌套類,這些問題消失,同時保持適當的封裝,因爲嵌套類可以訪問其內部類的內部。

1

C#中嵌套類的常見用途包括您的類內部使用的,您不希望在模塊的內部名稱空間中公開的類。例如,你可能需要拋出一個你不暴露給外部世界的異常。在這種情況下,你會想讓它成爲一個嵌套類,以便其他人不能使用它。

另一個例子是二叉樹的Node類。這不僅是你不想在課堂以外暴露的東西,而且它可能需要訪問私人成員進行內部操作。

0

有嵌套類的優點和缺點。圍繞着故意使用的專業人員中心,例如銥星提到的IEnumerator<T>和嵌套類以促進Command PatternWPF/MVVM。 SQL創建,讀取,更新和刪除(CRUD)操作在使用這些模式的業務線/數據驅動應用程序的代碼中封裝在類/命令中很受歡迎。

與嵌套類相關的負面因素與調試有關 - 嵌套的類越多,複雜性越高,引入錯誤越容易,調試它就越困難。即使使用像命令模式這樣的組織,也可能會因爲太多的類/命令而使你的類膨脹。