Scala 中的 Python 风格装饰器

Jul*_*éon 5 python scala decorator

在 Python 中,我可以做这样的事情:

def wrap(f):
    def wrapper(*args, **kwargs):
        print "args: ", args, kwargs
        res = f(*args, **kwargs)
        print "result: ", res
        return res
    return wrapper
Run Code Online (Sandbox Code Playgroud)

这让我可以包装任何函数,而不管它们采用什么参数。例如:

In [8]: def f(thing):
    print "in f:", thing
    return 3

In [9]: wrapped_f = wrap(f)

In [10]: wrapped_f(2)
args:  (2,) {}
in f: 2
result:  3
Out[10]: 3
Run Code Online (Sandbox Code Playgroud)

有没有办法在 Scala 中做类似的事情(编写一个可以应用于任何函数的包装器,无论其输入/输出类型如何)?

Mat*_*nen 3

这里有一个基本问题:在 Scala 中,您必须知道函数应该获取哪些参数并实际传递它们,以便编译器可以确保类型匹配。

说有def f(a: List[Int], b: String) = ...def g(args: Any*) = f(args)。这不会编译!(Any*指任意数量、任意类型的对象)。问题是,Any*仍然只有一个参数实际上被转换为一种Array.

为了更清楚地说明这一点,您可以考虑一个示例情况:您已使用wrap(f)某个函数调用了f(a: String, b: String)。然后,您将获得包装器的输出,该输出将以某种方式接受任意数量的任何类型的参数,然后您进行调用wrapper_f(List(1), "a")。在这种情况下wrapper_f(...),调用应该是正确的,但在包装器内部,包装函数具有完全不同的参数列表,不能接受 aList[Int]和 a String。因此,您会在运行时遇到“类型错误”,这在静态类型编程语言(或至少在 Scala 中)中(通常)应该是不可能的。