在Python中,我可以这样做:
class Demo:
def x(self, prefix, x, y):
print("Demo.x, prefix=%s, x=%s, y=%s" % (prefix, x, y))
return 3
def y(self, prefix, i):
print("Demo.y, prefix=%s, i=%d" % (prefix, i))
class Wrapper:
def __init__(self, inst, prefix):
self.inst = inst
self.prefix = prefix
def __getattr__(self, name):
print("function %s is called" % name)
func = getattr(self.inst, name)
return lambda *args, **kwargs: func(self.prefix, *args, **kwargs)
if __name__ == "__main__":
inst = Demo()
wrapper = Wrapper(inst, "prefix")
print(wrapper.x("a", "b"))
wrapper.y(123)
在这段代码中我可以使用包装器来提供统一的前缀,而无需在类Wrapper中重新定义类Demo的所有方法。
我只是想知道如何在Java中实现相同的东西?
我看了动态代理,但似乎无法改变论点。
这是我试过的:
public class Wrapper {
private Class cls;
private final Object inst;
private final String header;
public Wrapper(Class cls, Object inst, String header){
System.out.println("C=" + cls.getName());
this.cls = cls;
this.inst = inst;
this.header = header;
}
public Object invoke(String funcName, Object ...args)
throws InvocationTargetException, IllegalAccessException {
for (Method method : this.cls.getMethods()) {
if (method.getName().equals(funcName)) {
ArrayList argList = new ArrayList(Arrays.asList(args));
argList.add(0, header);
return method.invoke(this.inst, argList.toArray());
}
}
return null;
}
}
可以用作:
Wrapper wrapper = new Wrapper(DemoService.class, service, "prefix");
return (String)wrapper.invoke("test", "this is a test");
然而,"调用"方法不是那么直观和方便。
答案 0 :(得分:0)
实现所需包装器功能的一种方法是使用Java 8的泛型和功能接口的组合:
public class Wrapper<P1> {
@FunctionalInterface
public interface TriFunction<P1, P2, P3, R> {
R apply(P1 p1, P2 p2, P3 p3);
}
private P1 value;
public Wrapper(P1 value) {
this.value = value;
}
public <R> R invoke(Function<P1, R> func) {
return func.apply(value);
}
public <R, P2> R invoke(BiFunction<P1, P2, R> func, P2 value2) {
return func.apply(value, value2);
}
public <R, P2, P3> R invoke(TriFunction<P1, P2, P3, R> func, P2 value2, P3 value3) {
return func.apply(value, value2, value3);
}
}
您可以将此包装器与方法引用(:: operator)一起使用,如下所示:
public class A {
public String identity(String value) {
return value;
}
public String concat(String value1, String value2) {
return value1 + value2;
}
public String concat(String value, int val) {
return value + val;
}
public String concat(String value1, String value2, int val) {
return value1 + value2 + val;
}
public static void main(String[] args) {
Wrapper<String> wrapper = new Wrapper<>("toto");
A a = new A();
wrapper.invoke(a::identity); // returns "toto"
wrapper.invoke(a::concat, "tutu"); // returns "tototutu"
wrapper.invoke(a::concat, 10); // returns "toto10"
wrapper.invoke(a::concat, "tutu", 10); // returns "tototutu10"
}
}
此解决方案引入了简单类型的装箱,因此您可能希望提供接受invoke
,IntFunction
等的ObjIntFunction
方法。它也只处理最多3个参数的调用方法,但我认为处理更多的模式很容易理解。