簡體   English   中英

以類型安全的方式編寫類

[英]Writing a class in a type-safe way

我想寫一個類型安全的代碼。 這是我嘗試過的:

public interface ResultTronsformer<T>{
    public T tranform(T t);
}

public class BigDecimalTransformer implements ResultTRansformer<BigDecimal>{

    public BigDecimal transform(BigDecimal t){
        return t.setScale(0);
    }
}

現在我定義了看起來像的Column接口

public interface Column{
    public ResultTransformer<?> getTransformer();
}

並希望在方法中使用它

public class Report{
    private Map<Column, Object> columnValuePairs;

    public void putIntoACollection(Column c, Object columnsValue){
         ResultTransformer<?> rt = c.getTransformer();
         columnValuePairs.put(c, rt.transform(o)); //Error: Couldn't convert Object 
                                                   //to the capture of wildcard
    }
}

如何重新設計設計以達到理想的類型安全性? 也許我應該在運行時進行類型檢查(拋出異常)?

您可以考慮使用Column,就像它是某種具有特定類型的容器一樣。 這樣,您可以在Column聲明中引入泛型類型。

public interface Column<T>{
    public ResultTransformer<T> getTransformer();
}

然后,您可以更改Report方法,如下所示:

public <T> void putIntoACollection(Column<T> c, T columnsValue){
        ResultTransformer<T> rt = c.getTransformer();
        columnValuePairs.put(c, rt.transform(columnsValue)); 
}

您可以更改Column類並使其參數化:

public interface Column<T> {
    public ResultTransformer<T> getTransformer();
}

然后你必須參數化putIntoACollection方法(不需要參數化Report ):

public class Report {
    private Map<Column, Object> columnValuePairs;

    public <T> void putIntoACollection(Column<T> c, T columnsValue) {
        final ResultTransformer<T> rt = c.getTransformer();
        columnValuePairs.put(c, rt.transform(columnsValue));
    }
}

這樣,您永遠不需要使用捕獲類型。

以下是如何使用它的示例:

private class BigDecimalColumn implements Column<BigDecimal> {
    @Override
    public ResultTransformer<BigDecimal> getTransformer() {
        return new BigDecimalTransformer();
    }
}

public static void main(String[] args) {
    final Report report = new Report();
    report.putIntoACollection(new BigDecimalColumn(), new BigDecimal("3.14"));
}

獲取轉換器時,需要指定類型,因為編譯器當時不會知道它。

一種可能的解決方案是將類作為參數添加到Column的getTransformer並返回專門的ResultTransformer。

public interface ResultTransformer<T> {
    public T transform(T t);
}

public interface Column{
    public <T> ResultTransformer<T> getTransformer(Class<T> theClass);
}

public class Report{
   private Map<Column, Object> columnValuePairs;

   public void putIntoACollection(Column c, Object o){
       ResultTransformer<Object> rt = c.getTransformer(Object.class);
       columnValuePairs.put(c, rt.transform(o));
   }

public interface ResultTransformer<T> {
    public T transform(T t);
}

另一種方法是概括接口Column。

我們可以放棄所有的借口,只使用該死的原始類型

     ResultTransformer rt = c.getTransformer();

一個更自命不凡的解決方案 -

    static <T> T transform (ResultTransformer<T> rt, Object obj)
    {
        T t = (T)obj; // unchecked cast
        return rt.transform(t);
    }


public void putIntoACollection(Column c, Object obj){
     ResultTransformer<?> rt = c.getTransformer();
     columnValuePairs.put(c, transform(rt, obj) );

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM