簡體   English   中英

如何在接口中重載方法?

[英]How would I overload method in an interface?

如果我有這個界面

public interface someInterface {
  // method 1
  public String getValue(String arg1);
  // method 2
  public String getValue(String arg1, String arg2);
}

我希望能夠將 1 或 2 個字符串傳遞給 getValue 方法,而不必在每個實現類中都覆蓋它們。

public class SomeClass1 impelments someInterface 
{
 @Override
 public String getValue(String arg1);
}

public class SomeClass2 implements someInterface 
{
 @Override
 public String getValue(String arg1, String arg2);
}

這是行不通的,因為 SomeClass1 需要實現方法 2,而 SomeClass2 需要實現方法 1。

我堅持這樣做嗎?

public interface someInterface2 {
  public String getValue(String... args);
}

public class SomeClass3 implements someInterface2 
{
  @Override
  public String getValue(String... args) {
    if (args.length != 1) {
      throw IllegalArgumentException();
    }
    // code
  }
}

public class SomeClass4 implements someInterface2
{
  @Override
  public String getValue(String... args) {
    if (args.length != 2) {
      throw IllegalArgumentException();
     }
    // code
  }
}

someInterface2 someClass3 = new SomeClass3();
someInterface2 someClass4 = new SomeClass4();
String test1 = someClass3.getValue("String 1");
String test2 = someClass4.getValue("String 1, "String 2");

有沒有更好的方法來做到這一點?

接口充當該接口用戶的契約:您指定哪些方法可用(在所有實現中)以及如何調用它們。 如果接口的兩個實現需要一種不同的方法,則該方法應該是接口的一部分:

public interface Lookup {
}

public class MapLookup implements Lookup {
    public String getValue(String key) {
        //...
    }
}

public class GuavaLookup implements Lookup {
    public String getValue(String row, String column) {
        // ...
    }
}

在你的程序中,你會知道你使用的是哪個實現,所以你可以簡單地調用正確的函數:

public class Program {
    private Lookup lookup = new MapLookup();

    public void printLookup(String key) {
        // I hardcoded lookup to be of type MapLookup, so I can cast:
        System.out.println(((MapLookup)lookup).getValue(key));
    }
}

替代方法

如果你的類Program更通用並且使用依賴注入,你可能不知道你有哪個實現。 然后,我會創建一個新的接口Key ,它可以是任何一種類型的鍵:

public interface Lookup {
    // ...

    public String getValue(Key key);
}

public interface Key {
}

public MapKey implements Key {
    private String key;
    // ...
}

public GuavaKey implements Key {
    private String row, column;
    // ...
}

程序中的依賴注入可能來自某些工廠實現。 由於您無法知道您使用的是哪種類型的查找,因此您需要為getValue制定一個合同。

public interface Factory {
    public Lookup getLookup();
    public Key getKey();
}

public class Program {
    private Lookup lookup;

    public Program(Factory factory) {
        lookup = factory.getLookup();
    }

    public void printLookup(Factory factory) {      
        System.out.println((lookup.getValue(factory.getKey()));
    }
}

從 Java 8 開始,您可以通過使用default關鍵字讓接口提供方法的實現。 因此,一個新的解決方案是提供這兩種方法的默認實現,這可能會引發異常,然后從默認接口派生實際實現。

無論如何,這里是你如何做到這一點:

public interface SomeInterface {
    // method 1
    default String getValue(String arg1) {
        // you decide what happens with this default implementation
    }

    // method 2
    default String getValue(String arg1, String arg2) {
        // you decide what happens with this default implementation
    }
}

最后,讓類覆蓋正確的方法

public class SomeClass1 implements SomeInterface {
    @Override
    public String getValue(String arg1) {
        return arg1;
    }
}

public class SomeClass2 implements SomeInterface {
    @Override
    public String getValue(String arg1, String arg2) {
        return arg1 + " " + arg2;
    }
}

一個解決方案(不是很優雅)可能看起來像這樣:

public abstract class SomeClass {
   public String getValue(String arg1) {
      throw new IllegalArgumentException();
   }
   public String getValue(String arg1, String arg2) {
      throw new IllegalArgumentException();
   }
}

public class SomeClass1 extends SomeClass {
   public String getValue(String arg1) {
      // return sth
   }
}

public class SomeClass2 extends SomeClass {
   public String getValue(String arg1, String arg2) {
      // return sth
   }
}

但是有一個缺點 - SomeClass1 和 SomeClass2 不能直接繼承其他類。

如果第二個值在某種意義上可以被認為是可選的,並且在調用時總是有 2 個參數,則可以創建一個包裝類,該類實現 2 參數接口,將 1 參數實現作為構造函數參數傳遞並在方法中調用它,例如某些東西像這樣:

interface A{
  method1(P1)
}

interface B{
  method2(P1, P2)
}

class Wrap implements B{
  Wrap(A impl)

  override method2(P1, P2){
    call impl.method1(P1)
  }

}
public interface SomeInterface {
    default void print(String s) {
        System.out.println(s);
    }
}

public class SomeClass implements SomeInterface {
    /**
     * Note the this overloads {@link SomeInterface#print(String)}, 
     * not overrides it!
     */
    public void print(int i) {
        System.out.println(i);
    }
}

暫無
暫無

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

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