c++函函数到Java,重载操作符()()
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 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>
中,以允许所有具有访问器和删除操作的列表使用通用的通用算法进行排序。
- 重载操作符+:表达式必须是整型或无作用域枚举类型
- 重载操作符
- 如何重载操作符==外模板类使用友元函数
- 重载*操作符,使其在左右两边都工作
- 重载操作符<对于非随机迭代器
- 在c++中重载操作符的时间和原因
- 如何在c++中重载=操作符来通过引用进行复制
- 如何在c++中获取定义为友元的重载操作符的地址
- 使用重载操作符的文件操作表达式没有给出预期的结果
- 重载操作符()
- 重载操作符()并在类内使用
- 类中的重载操作符+
- 定时使用重载操作符
- c++带类的重载操作符
- 用列表容器重载[]操作符
- 重载操作符=
- 任何重载操作符()的静态检测
- 重载操作符以处理类对象
- 在使用另一个类的类中重载操作符==
- 派生类和基类中的重载操作符不同