11

如果我有这个界面

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");

有没有更好的方法来做到这一点?

4

5 回答 5

13

接口充当该接口用户的合同:您指定哪些方法可用(在所有实现中)以及如何调用它们。如果一个接口的两个实现需要不同的方法,那么该方法应该是接口的一部分:

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更通用并且使用依赖注入,你可能不知道你有哪个实现。然后,我会创建一个新的 interface 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()));
    }
}
于 2013-04-05T21:49:01.950 回答
11

从 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;
    }
}
于 2015-12-16T05:20:45.980 回答
2

一个解决方案(不是很优雅)可能看起来像这样:

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 不能直接继承其他类。

于 2013-04-05T21:15:54.523 回答
0

如果第二个值在某种意义上可以被认为是可选的,并且在调用时您总是有 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)
  }

}
于 2015-09-01T09:59:11.190 回答
0
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);
    }
}
于 2021-03-05T17:55:22.237 回答