如果我有这个界面
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");
有更好的方法吗?
答案 0 :(得分:10)
接口用作该接口用户的合同:指定可用的方法(在所有实现中)以及如何调用它们。如果接口的两个实现需要不同的方法,那么该方法不应该是接口的一部分:
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()));
}
}
答案 1 :(得分:2)
从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;
}
}
不错呃?
答案 2 :(得分:1)
一个解决方案(不是很优雅)可能看起来很喜欢这个:
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不能直接继承其他类。
答案 3 :(得分: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)
}
}
答案 4 :(得分: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);
}
}