2012-06-23 39 views
1

我想通用化返回 泛型基類的工廠方法。它的工作原理,但我得到 「BaseClass是一種原始類型...」的警告。Java - 返回通用基類型的工廠方法

我已經通過通用方法, Java文檔閱讀,但我還沒有完全得到如何做到這一點。

下面是一些代碼:

級#1

//base abstract class 
public abstract class BaseFormatter<T> 
{ 
    public abstract String formatValue(T value); 
} 

類#2

//two implementations of concrete classes 
public class FooFormatter extends BaseFormatter<Integer> 
{ 
    @Override 
    public String formatValue(Integer value) 
    { 
     //return a formatted String 
    } 
} 

類#3

public class BarFormatter extends BaseFormatter<String> 
{ 
    @Override 
    public String formatValue(String value) 
    { 
     //return a formatted String 
    } 
} 

工廠方法在一個單獨的類

public static BaseFormatter getFormatter(Integer unrelatedInteger) 
{ 
    if (FOO_FORMATTER.equals(unrelatedInteger)) 
     return new FooFormatter(); 
    else if (BAR_FORMATTER.equals(unrelatedInteger)) 
     return new BarFormatter(); 
    //else... 
} 

電話工廠方法從其他地方中的代碼

BaseFormatter<Integer> formatter = getFormatter(someInteger); 
formatter.formatValue(myIntegerToFormat); 

的問題是getFormatter()方法警告BaseFormatter是 原始類型,它是。我已經嘗試過各種各樣的東西,比如BaseFormatter 等。當然,我希望返回類型是通用的,如調用方法中聲明的 BaseFormatter。

請注意,格式化程序類型不是基於類的類型。例如並非所有Integer 值都使用FooFormatter格式化。有兩種或三種不同的方法可以對整數(或字符串或列表)進行格式化。這就是param unrelatedInteger的用途。

在此先感謝您的任何反饋意見。

+0

簡單的答案:Java類型系統無法安全地表達您想要的約束。這意味着你不能擺脫這個演員的警告。 – millimoose

回答

0

如果getFormatter在BaseFormatter定義,然後使用:

public static BaseFormatter<T> getFormatter(Integer unrelatedInteger) 

如果getFormatter在另一個類比BaseFormatter定義,然後使用:

public static BaseFormatter<?> getFormatter(Integer unrelatedInteger) 
+0

如果我做BaseFormatter ,我必須這樣做:public static BaseFormatter getFormatter(整數轉換器)。我不能這樣做,因爲返回新的FooFormatter()會導致錯誤。無法從FooFormatter轉換爲BaseFormatter ,所以這不起作用。 –

+0

@TJJJ看到我的更新 –

+0

我看了你的更新。問題在於:getFormatter在另一個類中定義。如果我返回一個未知類型的BaseFormatter(BaseFormatter ),這個方法很開心。但在調用方法中,我無法執行BaseFormatter formatter = getFormatter(someInteger);我得到一個類型不匹配錯誤。如果我將其更改爲BaseFormatter formatter = getFormatter(someInteger);那麼我不能傳入一個整數,因爲這個類型是未知的,而不是整數。 –

0

你actuaaly說,有沒有連接在作爲參數傳遞給getFormatter方法的輸入參數BaseFormatterunrelatedInteger之間。

我得到一些其他的警告:

Uncehcked Assignment: BaseFormatter to BaseFormatter<Integer> 

這個警告是比你指定的一個更壞。報告警告說,該用戶代碼可能嘗試插入BaseFormatter<String>BaseFormatter<Integer>,這東西會注意到只能在運行時失敗...考慮用戶不小心使用你的工廠方法類似這樣:

BaseFormatter<Integer> myUnsafeFormatter = 
     FormatterFactory.getFormatter(unrelatedIntegerForBarFormatter); 

編譯器可以不涉及unrelatedInteger與參數化類型返回BaseFormatter

另外,我會讓用戶顯式使用具體的格式化構造函數。所有格式化器共享的任何通用代碼都可以放入FormatterUtils類(只是不要讓該utils類增長太多......)。

0

學術語言中的某些類型系統可以表達所謂的相關和。 Java當然不能;那麼明智的是,getFormatter方法返回的對象的類型是什麼?我們可以做的最好的是BaseFormatter< ? extends Object >或簡稱BaseFormatter<?>,因爲IntegerString只有Object的共同點。爲什麼我們必須使用一個整數來決定返回哪個格式化程序,並且如果調用程序不知道格式化程序的類型,爲什麼調用程序需要一個更強的變量類型而不是BaseFormatter<?>

+0

好吧,從技術上說,它不需要任何東西超過BaseFormatter 。問題在於它使用BaseFormatter作爲排序接口,使用適當的數據類型調用相同的format()方法。在它接受Object並將其轉換爲正確類型之前。當然,這是一個問題,因爲它對類拋出異常是開放的。當對此進行通用化時,強制格式(arg)方法的數據類型是合理的。由於不同的格式化程序採用不同的類型,我不得不在超類中使用T.我唯一能想到的另一種方法是(繼續下一篇文章) –

+0

替換BaseFormatter formatter = getFormatter(someInteger); 與if語句並實例化正確的格式化程序。它在幾個地方叫,所以這是跛腳。我把這些代碼放在一個普通的位置上。但是爲了使FooFormatter和BarFormatter的工作方式相同(例如相同的方法調用,不同的argtype),它需要一個超類和抽象方法都必須實現。我正在考慮的另一個解決方案是使用CommonFormatter和重載格式(),所以我可以做cf.format(unrelatedInteger,myIntToFormat,cf.format(unrelatedInteger,myStrToFormat)。(繼續下一篇文章) –

+0

因爲我可以有幾個不同的格式(有2個以上,但本例保持爲2),這些方法中的每一個都會有一系列if語句,例如if(FOO_FORMATTER.equals(unrelatedInteger)) //做foo格式化; 否則如果(BAR_FORMATTER.equals(unrelatedInteger)) //做酒吧格式化我不喜歡那個,我願意接受任何人的建議。 –