Java 的 C++ 仿函数,重载运算符 ()()

C++ functors to Java, overloading operator ()()

假设一个简单的C++仿函数例子:

class Test2 {
    private:
        double a;

    public:
        Test2 (double a_) : a(a_){}
        double operator () () {return 10*a;}
};

template <typename Function>
double test ( Function function ) {return function();}

int main(int argc,  char* argv[]) {
    double a = test( Test2(5) );
    return 0;
}

有什么方法可以在 Java 中实现这个构造(例如使用接口 Functor)?你能给我一个简短的例子吗?感谢您的帮助。

你不会在 Java 中得到完全相同的东西,但你所做的事情的原则应该是相同的。

如果您想要 Java 中的仿函数可以像 functor_obj() 那样调用,那是不可能的。 Java 不允许运算符重载*,因此这种语法根本不可能。

然而,Java8引入了"Functional Interfaces"的概念,它被定义为任何具有一个[抽象**]功能的接口。任何时候你使用函数式接口,它的实例化都可以用 lambda 表达式代替。

Runnable run = () -> {System.out.println("Hello World (FROM THE SECOND DIMEN—I mean THREAD)");};
Thread thread = new Thread(run); 
//Also Equivalent to the two above lines:
//Thread thread = new Thread(() -> {System.out.println("Hello World (FROM THE SECOND DIMEN—I mean THREAD)");});
thread.start();
thread.join();

如果你想调用这个特定的仿函数,你只需像调用任何其他实现接口的对象一样调用它:

run.run();

因为 Java Lambda 表达式所做的是隐藏实现。以下代码:

Runnable run = () -> {System.out.println("Hello World (FROM THE SECOND DIMEN—I mean THREAD)");};

与 Java 7 等效代码做同样的事情:

Runnable run = new Runnable() {
    public void run() {
        System.out.println("Hello World (FROM THE SECOND DIMEN—I mean THREAD)");
    }
};

所以对于你的例子,你可能会这样写:

public static double test(Supplier<Double> f) {//imported from java.util.function
    return f.get();
}

然后可以这样调用:

double a = test(() -> 25);

这等同于您在原始 main 函数中编写的代码。如果您需要存储仿函数以供将来使用,您可以这样写:

Supplier<Double> sup = () -> 25;
double a = test(sup);
/*sup can now be stored somewhere or passed to a different function.*/

* - 我的意思是,Java 确实对 String 对象进行了运算符重载,以允许使用 + 来连接对象,但这几乎是唯一使用它的情况.

** - Java 8 还向接口引入了"Default"方法,允许接口有实现的方法。这可能看起来很奇怪,直到你意识到它允许你写像 public default void sort() 这样的东西,它可以添加到 java.util.List<T> 以允许所有列表,它们具有访问器和删除操作,使用通用的、通用的进行排序算法。

在Java8中,可以使用DoubleSupplier接口从一个对象中得到一个double值:

public class Test implements DoubleSupplier {
    private double a;
    public Test(double a) { this.a = a; }
    public double getAsDouble() { return 10 * a; }

    public static double test(DoubleSupplier ds) { 
        return ds.getAsDouble();
    }
    public static void main(String[] args) {
        double a = test(new Test(5));
    }
}

如果您不使用 Java 8,那么您可以创建自己的接口来实现:

public interface MyDoubleSupplier {
    double getAsDouble();
}

在 Java 中没有完全等价的东西,因为没有什么比重载 () 的含义更能像在 C++ 中那样。

从 Java8 开始,您可以在 Java 中以函数式风格编程,并且包 java.util.function.

中有许多标准函数式接口

你可以这样做:

import java.util.function.DoubleSupplier;

public double test(DoubleSupplier supplier) {
    return supplier.getAsDouble();
}

public DoubleSupplier newSupplier(double a) {
    return () -> 10 * a;
}

// use it:
double a = test(newSupplier(5));