[英]How can i make this work with java generics
假設我有這個接口和混凝土:
public interface MeterValue {}
public class MeterValueA implements MeterValue {}
public class MeterValueB implements MeterValue {}
public interface ReportBuilder<T extends MeterValue> {}
public class ReportBuilderA implements ReportBuilder<MeterValueA> {}
public class ReportBuilderB implements ReportBuilder<MeterValueB> {}
我有一個全局實例:
ReportBuilder<MeterValue> reportBuilder;
我想改變reportBuilder實例,如下所示:
if (isA())
reportBuilder = new ReportBuilderA();
else
reportBuilder = new ReportBuilderB();
reportBuilder.desiredMethod();
這樣做我得到“Type Missmatch”。 我怎樣才能獲得所需的功能? 或者我怎樣才能提高課堂設計的靈活性?
編輯:
通配符? 解決了這個問題。 但也介紹了其他問題。 假設我在界面中有這個方法:
public interface ReportBuilder<T extends MeterValue> {
public String getStuff(List<T> values);
}
public class ReportBuilderA implements ReportBuilder<MeterValueA> {
@Override
public String getStuff(List<MeterValueA> values) { return "A"; }
}
public class ReportBuilderB implements ReportBuilder<MeterValueB> {
@Override
public String getStuff(List<MeterValueB> values) { return "B"; }
}
說我有這個實例:
ReportBuilder<? extends MeterValue> reportBuilder = new ReportBuilderA();
和:
List<? extends MeterValue> list = new ArrayList<MeterValueA>();
String s = reportBuilder.getStuff(list);
由於列表包含通配符,因此對getStuff(...)的調用將不起作用。 一個修復方法是將ReportBuilder接口方法修改為:
public String getStuff(List<? extends MeterValue> values);
但后來我打破了具體的ReportBuilders。 (列表也是一個內容可能不同的全局實例)
有任何想法嗎?
我認為你應該將報告構建器變量聲明為:
ReportBuilder<? extends MeterValue> reportBuilder;
這允許reportBuilder
具有任何ReportBuilder
類,具有泛型類型的MeterValue
,或任何實現該接口的類。
順便說一句,如果您已經不熟悉它,創建ReportBuilder
實例似乎與工廠方法模式類似,可能值得閱讀它。 (當然還有其他模式。)
public interface MeterValue {}
public class MeterValueA implements MeterValue {}
public class MeterValueB implements MeterValue {}
public interface ReportBuilder<T extends MeterValue> {
void desiredMethod();
}
public class ReportBuilderA implements ReportBuilder<MeterValueA> {
@Override
public void desiredMethod() {}
}
public class ReportBuilderB implements ReportBuilder<MeterValueB> {
@Override
public void desiredMethod() {}
}
void f() {
ReportBuilder<? extends MeterValue> reportBuilder = null;
if (Math.random() > 0.5)
reportBuilder = new ReportBuilderA();
else
reportBuilder = new ReportBuilderB();
reportBuilder.desiredMethod();
}
哪里: ReportBuilder<? extends MeterValue>
ReportBuilder<? extends MeterValue>
表示泛型參數可以擴展MeterValue接口。
請參閱教程以閱讀有關通配符聲明的更多說明。
注意:請在特定情況下查看此代碼,以避免並行繼承氣味。 如果要添加一些新的MeterValue,你應該添加ReportBuilder它應該意味着你可能有這個問題。
編輯:
您不能將具有MeterValue子類型的數組傳遞給ReportBuilderA,它至少會重新記錄MeterValueA。 它不是類型安全的技術。 繼承后實例化具體類更適合C ++。 在Java中,最好不要在繼承后更改受限類型。
可能的解決方案,可能適用於您的具體案例:
1)為MeterValue使用單個接口。 所有差異都轉移到ReportBuilder繼承。 這意味着您在項目中具有並行繼承。
2)調用getStuff()
方法時使用具體的List<MeterValueA>
。 處理List<MeterValueA>
和List<MeterValueB>
所有共享邏輯都移動到帶簽名的方法: public void sharedLogic(List<? extends MeterValue> list)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.