簡體   English   中英

我如何使用java泛型來完成這項工作

[英]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.

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