c++函函数到Java,重载操作符()()

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

本文关键字:重载 操作符 Java 函数 c++      更新时间:2023-10-16

假设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 8中,您可以使用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,那么您可以创建自己的接口来实现from:

public interface MyDoubleSupplier {
    double getAsDouble();
}

在Java中没有完全等价的,因为没有像在c++中那样重载()的含义。

由于Java 8可以在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));

在Java中您不会得到完全相同的结果,但是您所做的工作的原则应该是相同的。

如果你想在Java中调用一个像functor_obj()这样的函子,那是不可能的。Java不允许操作符重载*,所以这种语法是不可能的。

然而,Java 8引入了"功能接口"的概念,它被定义为只有一个[抽象**]函数的任何接口。任何时候使用函数式接口时,都可以用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还为接口引入了"默认"方法,允许接口具有实现的方法。这可能看起来很奇怪,直到您意识到它允许您编写像public default void sort()这样的东西,可以将其添加到java.util.List<T>中,以允许所有具有访问器和删除操作的列表使用通用的通用算法进行排序。