gpt4 book ai didi

java - 包装器提供统一的方法参数

转载 作者:太空宇宙 更新时间:2023-11-04 11:19:37 24 4
gpt4 key购买 nike

在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来提供统一的前缀,而无需在类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");

但是,“调用”方法就不是那么直观和方便了。

最佳答案

实现您想要的包装器功能的一种方法是使用 Java 8 的泛型和函数接口(interface)的组合:

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

您可以将此包装器与方法引用(::运算符)一起使用,如下所示:

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"
}
}

此解决方案引入了简单类型的装箱,因此您可能需要提供一个接受 IntFunctionObjIntFunction 等的 invoke 方法。它还只处理最多 3 个参数的调用方法,但我认为处理更多参数的模式很容易弄清楚。

关于java - 包装器提供统一的方法参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45073965/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com