Java的C ++仿函数,重载operator()()

时间:2016-08-17 20:35:17

标签: java c++ interface operators functor

假设一个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)?你能给我一个简短的例子吗?谢谢你的帮助。

3 个答案:

答案 0 :(得分:2)

在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,那么您可以通过以下方式创建自己的接口:

public interface MyDoubleSupplier {
    double getAsDouble();
}

答案 1 :(得分:1)

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

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

然而,Java 8引入了&#34; Functional Interfaces&#34;的概念,它被定义为任何具有一个[abstract **]功能的接口。只要您使用功能界面,就可以用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 DOES对String个对象进行运算符重载以允许使用+来连接对象,但这几乎是唯一的情况。使用过。

** - Java 8还引入了&#34;默认&#34;接口的方法,允许接口具有已实现的方法。这可能看起来很奇怪,直到你意识到它可以让你写public default void sort()这样的东西,可以添加到java.util.List<T>以允许所有具有访问器和删除操作的列表使用通用的,通用的算法

答案 2 :(得分:1)

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