Is there an equivalent to C++ member function pointers in Java? [duplicate]
Before you mark as a dup, yes I've seen Function Pointers in Java, and no, it didn't really answer my question, basically because I'm pretty new to Java, so I didn't really understand allot of the answers.
This is kind of some mashed up Java / C++, is there any reasonable way to do this in Java?
public class Foo {
private int _data;
/* various other functions */
public boolean test1( Foo other ) { /* do test */ }
public boolean test2( Foo other ) { /* do test */ }
public boolean test3( Foo other ) { /* do test */ }
public boolean test4( Foo other ) { /* do test */ }
}
public class Bar {
private Foo[] _foos = { /* Init an array of Foos */ };
public Bar doSomething() {
_foos = new Foo[4];
_foos[0] = getTest(Foo::test1);
_foos[1] = getTest(Foo::test2);
_foos[2] = getTest(Foo::test3);
_foos[3] = getTest(Foo::test4);
}
/*
* Now we only have a single function which takes function pointer.
*/
private Foo _getTest(boolean Foo::*func()) {
Foo current = _foos[ 0 ];
for ( int i = 1; i != _foos.length; i++ )
current = current.*func( _foos[ i ] ) ? _foos[ i ] : current;
开发者_如何学C
return current;
}
}
No, there is simply no such thing in Java as a Function. There are only Objects and methods which are wholly owned by objects and subordinate to them. The object is your lord and master in java, nothing happens but through his will.
You can implement a sort of java-delegation by making your objects implement delegate interfaces, that's as close as it gets.
public interface Func {
boolean func(Foo foo);
}
public class Test1 implements Func {
@Override
public boolean func(Foo foo) {
return doSomeStuff();
}
...
_foos[0] = getTest(new Test1());
hope that's enough to get the idea across. In general you don't see that actually done much in application code.
edit:
Since you're new to Java, syntax to actually do what you were trying to do. Which may also illuminate what a pita it is and why people don't like it :)
public class Bar {
public static interface Func {
boolean func(Foo current, Foo other);
}
public static Func test1 = new Func() {
@Override
public boolean func(Foo current, Foo other) {
return current.test1(other);
}
};
public Bar doSomething() {
_foos = new Foo[4];
_foos[0] = getTest(test1);
//...
}
private Foo _getTest(Func func) {
Foo current = _foos[ 0 ];
for ( int i = 1; i != _foos.length; i++ ) {
current = func(current, _foos[ i ] ) ? _foos[ i ] : current;
}
return current;
}
}
Functions in Java are not first class objects. That means the best way you can do this is by subclassing or by implementing an interface. The interface will contain the method definition. Then you will be actually passing an object with the desired method. See for example how Collection.sort works.
JDK8 may introduce lambdas and method references.
In the mean time anonymous inner classes provide a slightly verbose way of creating functor objects.
public interface FooTest {
boolean test(Foo foo);
}
[...]
FooTest[] tests = {
new FooTest() { public void boolean test(Foo foo) {
return foo.test1();
}},
[...]
};
For building the likes of test frameworks, then reflection or the static code generation with annotation processors is the way to go. (Note that generally reflection is evil, but it okay in situations such as testing frameworks.)
You cannot point to a function in Java and there is no direct equivalent.
The only thing I can think of would be Function objects. You know, where in C++ you would overload the function call operator,
operator()
In Java, you create an interface called Function
with a virtual method doSomething
and then instead of an array of function pointers as you'd do in C you have an array of Function
objects whose doSomething
method you then call.
A more or less straightforward translation of your example into Java, given the differences in the languages.
public abstract class PTMF { // Pointer To Member Function
// The object on which we are going to call the method
public Foo self;
// Common interface of the member functions we are going to call
public abstract boolean test(Foo other);
}
public class Foo {
private int _data;
/* various other methods */
public boolean test1(Foo other) { /* do test */ }
public boolean test2(Foo other) { /* do test */ }
public boolean test3(Foo other) { /* do test */ }
public boolean test4(Foo other) { /* do test */ }
}
public class Bar {
private Foo[] _foos = { /* Init an array of Foos */ };
public Bar doSomething() {
_foos = new Foo[4];
// Here we are going to define inline some PTMFs
// providing adapter implementations for our interface call.
_foos[0] = getTest(
new PTMF() {
@Override public void test(Foo other) {
return self.test1(other);
}
}
);
_foos[1] = getTest(
new PTMF() {
@Override public void test(Foo other) {
return self.test2(other);
}
}
);
_foos[2] = getTest(
new PTMF() {
@Override public void test(Foo other) {
return self.test3(other);
}
}
);
_foos[3] = getTest(
new PTMF() {
@Override public void test(Foo other) {
return self.test4(other);
}
}
);
}
/*
* Now we only have a single function which takes function pointer.
*/
private Foo getTest(PTMF ptmf) {
Foo current = _fos[0];
for ( int i = 1; i != _foos.length; i++) {
// Set reference to called object
ptmf.self = current;
// Call PTMF
current = ptmf.test( _foos[ i ] ) ? _foos[ i ] : current;
}
return current;
}
}
Note that in the example above, PTMF is not thread-safe. For a thread-safe implementation, change PTMF to
public class PTMF {
public abstract boolean test(Foo self, Foo other);
};
or, better in this case:
public interface PTMF {
boolean test(Foo self, Foo other);
};
and the body of the loop in getTest()
would be:
current = ptmf.test(current, _foos[ i ] ) ? _foos[ i ] : current;
精彩评论