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));
假设一个简单的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));