[英]Scala-style abstract modules in C# or other languages?
我正在閱讀Martin Odersky的書“Scala編程”,其中有關抽象模塊的部分,以及他的論文可擴展組件抽象:
http://lampwww.epfl.ch/~odersky/papers/ScalableComponent.pdf
我的想法是,通過使您的模塊抽象類而不是對象 (或像Java中的經典靜態,全局模塊 ):
abstract class myModule{
// this is effectively an abstract module, whose concrete
// components can be configured by subclassing and instantiating it
class thing{}
class item{}
object stuff{}
class element{}
object utils{}
}
您可以實例化多個子類和具有不同具體特征的模塊實例。 這使您可以根據具體情況(例如,在測試期間替換數據庫組件,或在開發環境中替換IO組件)以及使用它們自己的模塊范圍的可變狀態集實例化多個模塊來不同地配置模塊。
根據我的理解,在基本層面上,唯一的硬性要求是您可以擁有嵌套類,這樣封閉類可以充當模塊。
它的另一個實際要求是你可以在多個文件中展開類定義,因為其中包含一堆類的模塊可能比單個源文件中的大多數代碼行更多。
Scala使用Traits做了這個,它帶來了一些其他好東西,這些好東西不是整個傳播抽象模塊類的核心,而不是多個源文件的想法。 C#具有partial classes
,它們提供相同的功能,並且還允許嵌套類。 據推測,其他一些語言對嵌套類具有類似的支持,以及在多個文件上拆分類。
這種模式是否出現在C#或任何其他語言的任何地方? 我認為許多語言的大型項目都面臨着抽象模塊要解決的問題。 是否有任何理由將“抽象類作為抽象模塊”的東西不起作用,因此沒有使用? 在我看來,這是一個比各種DI框架更清晰的解決方案,它提供了相同的功能。
通常的比較是ML模塊,其中Scala traits(或抽象類)扮演ML簽名的角色,他們的具體實現(通常是Scala對象)扮演ML結構的角色。 這里對ML模塊的討論應該使連接合理清晰。
Scala和ML之間的模擬是有意的,如果你看一下Scala編譯器的源代碼,你會發現Scala對象通常是使用包含“Module”作為一部分的名稱來引用的。
您描述的抽象模塊具有以下核心屬性:
能夠使用多個源文件指定模塊的功能不是核心要求,但它當然可以派上用場。
在最基本的形式中,模塊描述抽象數據類型(例如隊列):可用於與數據類型交互的操作以及交互所需的任何輔助類型。
在更復雜的形式中,它可以描述整個子系統(例如網絡)。
在命令式語言中,您通常使用接口來實現相同的目的:
如您所述,如果您的模塊具有大型接口(例如,描述子系統),則在一個文件中編寫實現豐富接口的類通常是不切實際的。 如果該語言不支持將同一個類拆分為單獨的源(或更准確地說:將同一類的不同部分從不同的源文件“粘合”在一起),解決方案通常是失去所附的要求並提供一系列指定它們之間交互的接口 - 因此您獲得了子系統的API(它是最純粹的API:它是與子系統交互的接口,尚未實現)。
在某些方面,后一種方法可以比封閉類型更通用(在你能用它實現的意義上是通用的):你可以提供來自不同作者的各種子類型(通過接口指定)的實現:只要子類型只依賴於指定的接口進行相互交互,這種混合匹配方法將起作用。
大多數函數式編程語言的優勢之一是參數化數據類型,您可以在其中實例化另一個日期類型作為其參數(例如,整數隊列)。 Java / C#中的泛型(以及C ++中的模板)實現了相同的靈活性。 當然,基於類型系統的語言之間的確切含義和表達能力可能不同。
整個討論是獨立形式的依賴注入(DI),它試圖通過顯式提供所需的部分(而不是具有實現選擇)來放松類型的具體實現與其支持部分之間的強依賴性,作為用戶該類型可能更好地理解這些部分的哪些實現最適合實現其目標 - 例如,為測試功能提供模擬實現。
DI嘗試解決的問題是命令式語言所獨有的,你也可以在函數式語言中遇到相同的依賴性問題:抽象模塊的實現可能會選擇使用子類型的特定實現(從而將自身耦合到這些實現)而不是將子類型實現作為參數(這是DI的目標)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.