ege*_*lev 17 java design-patterns code-duplication
我想知道是否有可能要求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
}
Run Code Online (Sandbox Code Playgroud)
我想避免代码重复.我的想法是这样的:
public void useMyMethod(A|B obj){
obj.myMethod();
}
Run Code Online (Sandbox Code Playgroud)
java中已有类似的语法类型.例如:
try{
//fail
} catch (IllegalArgumentException | IllegalStateException e){
// use e safely here
}
Run Code Online (Sandbox Code Playgroud)
显然这是不可能的.如何使用这种类型的不可编辑类型层次结构来实现设计良好的代码?
Yog*_*ter 15
将函数作为参数传递给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;
}
});
}
Run Code Online (Sandbox Code Playgroud)
对于Java> = 8,您可以使用Lambda表达式:
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());
}
Run Code Online (Sandbox Code Playgroud)
pbe*_*nyi 13
尝试使用适配器设计模式.
或者,如果可能,添加一些基本接口:
public interface Base {
void myMethod();
}
public interface A extends Base {}
public interface B extends Base {}
...
public void useMyMethod(Base b) {
b.myMethod()
}
Run Code Online (Sandbox Code Playgroud)
此外,您还可以使用类似的东西这个
你可以interface MyInterface用一种方法写一个myMethod.然后,对于要考虑作为有限集的一部分的每种类型,编写一个包装类,如下所示:
class Wrapper1 implements MyInterface {
private final Type1 type1;
Wrapper1(Type1 type1) {
this.type1 = type1;
}
@Override
public void myMethod() {
type1.method1();
}
}
Run Code Online (Sandbox Code Playgroud)
然后你只需要使用一个MyInterface而不是一个有限类型的类型,并且总是会调用相应类型的适当方法.
请注意,要实际使用这些包装类来调用myMethod您必须编写的方法
myMethod(new Wrapper1(type1));
Run Code Online (Sandbox Code Playgroud)
这将变得有点难看,因为您将不得不记住集合中每种类型的包装类的名称.因此,您可能更愿意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();
}
Run Code Online (Sandbox Code Playgroud)
然后你可以使用代码调用方法
myMethod(MyWrapper.of(type1));
Run Code Online (Sandbox Code Playgroud)
这种方法的优点是无论您使用哪种类型,代码都是相同的.如果您使用此方法,则必须implements MyInterface在Wrapper1声明中替换extends MyWrapper.
那么,建模你的需求的正确方法是在超类型接口C中声明myMethod(),A和B都扩展; 然后,您的方法接受类型C作为其参数.在您描述的情况下,您无法执行此操作这一事实表明您没有以实际反映其行为方式的方式对类层次结构进行建模.
当然,如果你不能改变界面结构,那么你总是可以用反射来做.
public static void useMyMethod(Object classAorB) throws Exception {
classAorB.getClass().getMethod("myMethod").invoke(classAorB);
}
Run Code Online (Sandbox Code Playgroud)