簡體   English   中英

具有多個 class 實現相同接口的方法

[英]method with multiple class implementing same interface

我有一個界面:

public interface I {
   getBar();
}

我有 2 class: AB實現I

我想做的是:

public void foo(List<I> items) {
   for (I item : items){
      if (item instanceof A) this.append((A) item);
      if (item instanceof B) this.append((B) item);
   }
}

有沒有 java 8 的東西可以讓我沒有那個instanceof列表並這樣稱呼它?

items.foreach(this::append);

注意:我可以做一些像item.add(this)這樣的事情,它會 append 本身到this但是然后我會在 object 上調用一個方法來修改參數(並且只有它)但是正如 Robert C 所述,這是不好的做法。馬丁的“清潔代碼”:

Arguments 最自然地被解釋為 function 的輸入。

任何強迫您檢查 function 簽名的行為都等同於雙重考慮。 這是一種認知障礙,應該避免。 在面向 object 的編程之前的日子里,有時需要 output arguments。但是,在 OO 語言中,對 output arguments 的大部分需求都消失了

只需將 instanceof 的東西移動到通用的 append func

private void append(I item) {
  if (item instanceof A) ...
  if (item instanceof B) ...
}

那么你可以使用

items.foreach(this::append);

如果你采取更多 OOP 方法怎么辦,

  1. 定義附加程序
interface Appender{ void append(I item); }
  1. 為 AB 創建你的 appender 和什么都不做的默認 appender
  2. 將 appender 放入 map Map<Class,Appender>
  3. 將您的代碼更改為
 for (I item: items){ appenders.getOrDefault(item.class,DEFAULT_APPENDER).append(item); }

你正在考慮它。

您的 class 獲取I的這些實例,並根據類型具有不同的重載方法。 此重載意味着它需要了解所有實現,以便為每個實現提供不同的重載。

顯然,問題在於列表必須隨着實現的添加而增長。

解決方案是讓I實現負責了解它們是如何附加的。

public interface I {
    Bar getBar(); /* you missed the return type, but anyway */

    void appendTo(SomeType foo);
}

你的方法就變成了

public void foo(List<I> items) {
   for (I item : items){
      item.appendTo(this); //or instead of this, some append-able instance 
   }
}

如果有人添加I的新實現,他們將被迫編寫一個 append 方法作為接口契約的一部分。

實際答案:這是一個雙重調度問題,以 Java 為中心的解決方案是訪問者模式,它有很多變化。

愚蠢的回答:只是為了好玩,這里沒有instanceof

    private static final Map<Class<?>, Consumer<I>> DISPATCHER = Map.of(
      A.class, this::appendA,
      B.class, this::appendB
    );

    items.forEach(i -> DISPATCHER.get(i.getClass()).accept());

是的,它仍然很分支,必須運行更多的指令才能得到相同的結果:)

暫無
暫無

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

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