當使用欄位中特殊的標記來區別物件類型時,可能會產生標記對相關資料誤貼標籤的錯誤 ― 通稱為 Impostor Type 錯誤模式。在診斷 Java 代碼的這一部分中,Eric Allen 對這個錯誤的癥狀和起因進行了分析,詳細說明了預防錯誤發生的方法,並討論了一種迷人的混合實現方法,這種方法不使用 impostor type,但最後,還是有很多相同的缺點產生。請在 討論論壇與作者及其他讀者分享您對本文的看法。
程式中除了最無關緊要的部分外都要對某些資料類型進行操作。靜態類型系統提供了一種方法,它能夠確保程式不會對給定類型的資料進行不當的操作。Java 語言的優點之一是嚴格的區分類型,所以在程式運行前已消除了類型錯誤。作為開發人員,我們可以使用這個類型系統提供更健壯且沒有錯誤的代碼。然而,我們卻常常沒有讓類型系統發揮出最大的潛力。
Impostor Type 錯誤模式
很多程式可以更多地使用靜態類型系統,但它們沒有這樣做,而是依賴包含區別資料類型標記的特殊欄位。
依靠這些特殊欄位區別資料類型,這樣的程式放棄了類型系統專門提供給它們的保護措施。當這些標記中的一個對它的資料誤貼了標籤,就會產生我稱之為 Impostor Type的錯誤。
癥狀
impostor type 錯誤的一種常見癥狀是很多概念上不同類型的資料都被同樣(並且錯誤)的方式處理。另一常見癥狀是資料與任何指定的類型都不匹配。
首要規則是,只要當概念上的資料類型和它被程式處理的方法不匹配,就可以懷疑是否發生了這個模式的錯誤。
為說明引入這種模式的錯誤是多麼的輕而易舉,讓我們來考慮一個簡單的樣本。假設我們需要處理各種各樣的歐幾裡得幾何學形狀,如圓形、正方形等等。這些幾何形狀沒有座標,但含有一個 scale 變數,所以可以計算它們的面積。
清單 1. 用 imposter type 實現各種幾何形狀
public class Form {
String shape;
double scale;
public Form(String _shape, double _scale) {
this.shape = _shape;
this.scale = _scale;
}
public double getArea() {
if (shape.equals("square")) {
return scale * scale;
}
else if (shape.equals("circle")) {
return Math.PI * scale * scale;
}
else { // shape.equals("triangle"), an equilateral triangle
return scale * (scale * Math.sqrt(3) / 4);
}
}
}