Scala概述(五)抽象(3)

2021-08-23 13:32:44 字數 1379 閱讀 2311

一種語言裡有兩套抽象語法體系肯定會讓人產生對這種語言複雜性的疑問:能不能就用一種形式化體系來實現?本節當中我們將會展示,函式式的型別抽象機制(也就是泛型)實際上可以通過物件導向的型別抽象機制(也就是抽象型別)來表達。這種表達方式的思路如下所述:

假定乙個引數化型別c有乙個型別引數t(可以直接推廣到多個型別引數的情況),那麼這種表達方式有四個關鍵組成部分:分別是型別自身的定義、型別例項的建立、基類構造子的呼叫以及這個類的型別例項(type instances)。 1.

型別定義,c的定義可以重寫如下:

classc

也就是說,c的型別引數可以用其抽象成員來重新定義。如果型別引數有上界或者下界,則可以帶到抽象成員的定義上。型別引數的協變性則不帶到抽象成員的定義上,參見第4點。 2.

以t為引數建立例項的呼叫:newc[t]可以寫成:

newc 3.

如果c[t]出現在呼叫基類構造符的場合,則其子類的定義將會進行如下擴充:

typet = t 4.

每乙個c[t]形式的型別定義都被擴充為如下的細化形式:

c  

如果t被宣告為非協變

c 如果t被宣告為協變

c 如果t被宣告為逆協變

這種表達方式在一種情況下會有問題:命名衝突。這是因為引數的名稱成為了類的成員,可能和其他成員衝突,包括其父類的型別引數轉化成的成員。這種衝突可以通過重新命名解決,例如給每個型別名稱指定乙個唯一數字標識。

兩種抽象模式之間可以轉換,對於一種語言還是有價值的,因為可以降低其內在的概念複雜性。例如,scala的泛型,實際上就是一種語法糖,完全可以被抽象型別替代掉。既然如此,也許會有人問,這種語法糖有沒有必要性?或者說為什麼不只用抽象型別呢,這樣可以使語法本身簡化很多。實際上,scala中引入泛型有兩重意義:首先,手工把泛型轉化為成為抽象型別表達形式並不那麼簡單,不僅會喪失語法的簡潔性,而且還可能帶來前述的命名衝突等問題。其次,泛型和抽象型別在scala中一般扮演不同的角色,泛型一般用於型別的例項化,而抽象型別主要用於在呼叫者**中對相應的抽象型別進行引用。後者主要來自於兩個場合:乙個是有人需要在客戶**中隱藏相關型別資訊,用於構造類似於sml模式的模組系統。另乙個是在子類中協變地繼承父類的型別,從而獲得族多型。

可能有人會問,那麼是否可以反過來用泛型來替代抽象型別呢?一些對於兩種抽象方式都支援的系統進行的研究[27]證實,這樣做要困難得多,至少整個程式都需要重寫。不僅如此,如果系統要實現受限多型的話,重寫型別上/下界的部分會呈平方級增長[8]。實際上這一點也不奇怪,因為這兩種型別體系的理論基礎就不同,泛型(不帶f-界的)可以用f<:系統來表達[11],而抽象型別則建立在型別依賴的基礎之上。後者比前者的表現力更強,例如,帶路徑依賴型別的vobj演算是可以涵蓋f<:的。

Scala概述(六)合成(3 總結)

在scala中,類的抽象與合成機制可以被視作面向服務的元件模型的基礎。軟體元件是乙個個有明確定義的,提供特定服務的計算單元。一般而言,乙個軟體元件並不是完全自含的,也就是說它的實現依賴於其他一系列提供相應服務的元件。在scala中,軟體元件即對應著類和trait,類和trait的具體成員相當於他們獲...

Scala抽象方法

如果在父類中,有某些方法無法立即實現,而需要依賴不同的子類來覆蓋,重寫實現不同的方法。此時,可以將父類中的這些方法編寫成只含有方法簽名,不含方法體的形式,這種形式就叫做抽象方法 乙個類中,如果含有乙個抽象方法或抽象field,就必須使用abstract將類宣告為抽象類,該類是不可以被例項化的 在子類...

scala實現抽象工廠

package com.linewell.modeldesgin.abstractfactory created by ctao on 2015 8 8.抽象工廠模式 工廠特質 trait skinfactory 按鈕特質 trait button 文字框特質 trait textfield 春天 ...