首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Java多类型方法参数?

Java多类型方法参数?
EN

Stack Overflow用户
提问于 2014-12-16 19:09:32
回答 7查看 15.4K关注 0票数 18

我想知道是否可以要求java方法参数是有限类型集中的任何类型。例如,我正在使用一个库,其中有两个(或更多)类型具有公共方法,但它们在类型层次结构中的最低公共祖先是Object。我这里的意思是:

   public interface A {
      void myMethod();
   }

   public interface B {
      void myMethod();
   }
...
   public void useMyMethod(A a) {
      // code duplication
   }

   public void useMyMethod(B b) {
      // code duplication
   }

我想避免代码重复。我的想法是这样的:

   public void useMyMethod(A|B obj){
      obj.myMethod();
   }

在java中已经有了类似类型的语法。例如:

  try{
     //fail
  } catch (IllegalArgumentException | IllegalStateException e){
     // use e safely here
  }

显然,这是不可能的。如何使用这种不可编辑的类型层次结构来实现设计良好的代码?

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2014-12-16 19:17:23

您可以使用单个方法myMethod编写一个interface MyInterface。然后,对于要考虑作为有限集的一部分的每种类型,编写一个包装类,如下所示:

class Wrapper1 implements MyInterface {

    private final Type1 type1;

    Wrapper1(Type1 type1) {
        this.type1 = type1;
    }

    @Override
    public void myMethod() {
        type1.method1();
    }
}

然后,您只需要使用MyInterface,而不是有限类型集中的一个,并且将始终调用来自适当类型的适当方法。

请注意,要实际使用这些包装类来调用方法myMethod,您必须编写

myMethod(new Wrapper1(type1));

这将变得有点难看,因为您必须记住集合中每个类型的包装器类的名称。因此,您可能更喜欢将MyInterface替换为具有多个静态工厂的抽象类,这些工厂生成包装器类型。如下所示:

abstract class MyWrapper {

    static MyWrapper of(Type1 type1) {
        return new Wrapper1(type1);
    }

    static MyWrapper of(Type2 type2) {
        return new Wrapper2(type2);
    }

    abstract void myMethod();
}

然后,您可以使用以下代码调用该方法

myMethod(MyWrapper.of(type1));

这种方法的优点是,无论您使用哪种类型,代码都是相同的。如果使用这种方法,则必须将Wrapper1声明中的implements MyInterface替换为extends MyWrapper

票数 8
EN

Stack Overflow用户

发布于 2014-12-16 19:34:55

如何将函数作为参数传递给useMyMethod函数?

如果您正在使用Java < 8:

public interface A {
    void myMethod();
}

public interface B {
    void myMethod();
}

public void useMyMethod(Callable<Void> myMethod) {
    try {
        myMethod.call();
    } catch(Exception e) {
        // handle exception of callable interface
    }
}

//Use

public void test() {
    interfaceA a = new ClassImplementingA();
    useMyMethod(new Callable<Void>() {
        public call() {
            a.myMethod();
            return null;
        }
    });

    interfaceB b = new ClassImplementingB();
    useMyMethod(new Callable<Void>() {
        public call() {
            b.myMethod();
            return null;
        }
    });
}

对于Java >= 8,可以使用Lambda Expressions

public interface IMyMethod {
    void myMethod();
}

public void useMyMethod(IMyMethod theMethod) {
    theMethod.myMethod();
}

//Use

public void test() {
    interfaceA a = new ClassImplementingA();
    useMyMethod(() -> a.myMethod());

    interfaceB b = new ClassImplementingB();
    useMyMethod(() -> b.myMethod());
}
票数 16
EN

Stack Overflow用户

发布于 2014-12-16 19:13:08

尝试使用Adapter设计模式。

或者,如果可能的话,添加一些基本接口:

public interface Base {
    void myMethod();
}

public interface A extends Base {}
public interface B extends Base {}
...
public void useMyMethod(Base b) {
    b.myMethod()
}

此外,您还可以使用类似于this的内容

票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27503251

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档