簡體   English   中英

支持不同類型參數的可變數量的 Java 接口方法

[英]Java Interface method supporting variable number of arguments with different types

我想構建一個包含一個方法的接口,該方法可以采用可變數量的各種類型的參數,如下所示:

interface MyInterface {

   boolean myMethod(Object ...args); <--HERE I WOULD LIKE TO PASS ANY NUMBER OF PARMS OF ANY TYPE

}

在接口的具體實現中,我想傳遞任意數量的任意類型的參數,如下所示:

class MyImpl1 implements MyInterface {

   boolean myMethod(Student s, Course d) {
      ...
   }
}

另一種實現可能如下:

 class MyImpl2 implements MyInterface {

   boolean myMethod(Department d) {
      ...
   }
}

在這方面,我在這里瀏覽了一些帖子,但對如何執行此操作沒有任何想法。 有人可以在這里幫忙嗎? 謝謝。

編輯:

我已經想到了確切的界面結構如下所示:

interface ConditionEvaluator {
     
     boolean evaluate(Object ...args);
     CondtionName getConditionName();
   }

一個具體的實現看起來像這樣:

class StudentEvaluator implements MyInterface {
  
    boolean evaluate(Student s, List<Course> courses) {
      ...
    }
  
    ConditionType getConditionType() {
       return ConditionType.STUDENT_PASSED;
    }
 }

為了使用這個,我想,我將創建一個枚舉映射,包含 ConditionType 作為鍵和具體實現作為值,如下所示:

Map<ConditionType, MyInterface> conditionTypeMap;

然后從調用方方法中,考慮基於適當的ConditionType派生適當的實現。

用法有點像下面,

我將有一個工廠類,如下所示:

@Component
public class ConditionEvaluatorFactory {

  private final Map<ConditionType, ConditionEvaluator> conditionEvaluatorMap;

  public ConditionEvaluatorFactory(List<ConditionEvaluator>
                                          conditionEvaluatorList) {
    Map<ConditionTyope, ConditionEvaluator> evaluatorMap =
        new EnumMap<>(ConditionEvaluator.class);
    for (ConditionEvaluator evaluator :
        conditionEvaluatorList) {
      evaluatorMap.put(evaluator.getConditionType(),
          evaluator);
    }
    this.conditionEvaluatorMap = evaluatorMap;
  }

  public ConditionEvaluator getEvaluator(ConditionType conditionType) {
    ConditionEvaluator evaluator = conditionEvaluatorMap
        .get(conditionType);
    if (evaluator == null) {
      throw new Exception("error message");
    }
    return evaluator;
  }
}

調用者類如下:

@component
class StudentUtil {

 @Autowired
 private ConditionEvaluatorFactory evaluatorFactory;

 public void callerFunc(Student s, List<Course> courseList) {
    boolean flag = evaluatorFactory.getEvaluator(ConditionType.STUDENT_PASSED).evaluate(s, courseList);
 ...
    
 }

讓我們從一個重要的點開始:我們有一個由多個子類實現的interface的原因是因為所有這些類共享相同的邏輯,即使它們遵循不同的實現。

在你的情況下,看起來你真的不能擁有一個接口(或者至少,你不能在不接受未知類型的變量列表並將它們轉換為靜態類型的情況下做到這一點)。

您的問題確實沒有理想的解決方案,但無論如何我都試圖彌補。

如果您的所有目標都是有一個點,您可以根據要檢查的條件簡單地調用評估器,那么您可以做的是聲明一個包含輸入映射的類:

public class Inputs {

    private final Map<String, Object> inputs = new HashMap<>();

    public static Inputs builder() {
        return new Inputs();
    }

    public Inputs push(String key, Object value) {
        inputs.put(key, value);
        return this;
    }

    public <T> T get(String key) {
        return (T) inputs.get(key); //<-- Unchecked cast, but somewhere you have to do it unfortunately
    }

}

然后,在您調用ConditionType的枚舉中,添加一個abstract方法,該方法在參數中接受Inputs並返回一個boolean作為評估結果。

一旦你這樣做了,你就可以在枚舉的每個特定值中實現特殊處理:

public enum ConditionType {
    STUDENT_PASSED {
        @Override
        public boolean evaluate(Inputs inputs) {
            Student student = inputs.get("student");
            List<Course> courses = inputs.get("courses");
            //do your logic with student and courses
            return false;
        }
    },
    DEPARTMENT_OPEN {
        @Override
        public boolean evaluate(Inputs inputs) {
            Department department = inputs.get("department");
            //do your logic with department
            return false;
        }
    };

    public abstract boolean evaluate(Inputs inputs);
}

這樣,在您的實用程序類中,您將能夠執行以下操作:

public class EvaluationUtils {

    public void callerFunc(Student student, List<Course> courses) {
        Inputs input = Inputs.builder()
                .push("student", student)
                .push("courses", courses);
        boolean flag = ConditionType.STUDENT_PASSED.evaluate(input);
        //...
    }

    public void callerFunc(Department department) {
        Inputs input = Inputs.builder()
                .push("department", department);
        boolean flag = ConditionType.DEPARTMENT_OPEN.evaluate(input);
        //...
    }

}

我在上述方法中看到的唯一優點是它避免了您在每個實現中進行檢查和強制轉換。

然而,它與您最初認為的聲明接口並沒有什么不同( boolean evaluate(Object...) ),每個實現都會獲取參數,檢查大小,類型然后繼續。 但是話又說回來,您的案例聽起來不像是可以分解為接口或任何共享方法的案例。

這就是泛型的用途。 定義你的接口:

interface MyInterface<T> {

    boolean myMethod(T arg);
}

那么您的基本單參數實現將是:

class MyImpl2 implements MyInterface<Department> {

    boolean myMethod(Department d) {
        ...
    }
}

並且您的兩個參數實現將需要一個持有人類:

class CourseEnrollment {
    Student s; Course d;
}

class MyImpl1 implements MyInterface<CourseEnrollment> {

    boolean myMethod(CourseEnrollment ce) {
        ...
    }
}

暫無
暫無

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

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