2

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;

        return current;
    }
}
Community
  • 1
  • 1
Robert S. Barnes
  • 39,711
  • 30
  • 131
  • 179

5 Answers5

8

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;
  }

}
Affe
  • 47,174
  • 11
  • 83
  • 83
  • Ugh, that dam orange bar that says "new answers submitted" is so annoying. You typed the exact same thing as me but faster :P – Andrew Nov 25 '10 at 18:53
  • @Affe: Why don't you see it much? Seems allot like C++ functors, which are very widely used. – Robert S. Barnes Nov 25 '10 at 18:59
  • 1
    Delving into my personal opinion, I think a lot of textbooks and early java literature included lots of general disdain for the constructs that tend to go with it (e.g., anonymous implementations) and taught us all that if you found yourself doing it a lot, you had a 'Bad OO' or "not OO to begin with" design. That "Good" OO code souldn't need much of this sort of thing. "If you find yourself needing functions, you missed the point of java." blah blah etc etc. There are of course obvious exceptions that we do use a lot like the Runnable interface and the Comparator interface. – Affe Nov 25 '10 at 19:05
  • @Affe: Could I nest this inside Bar? – Robert S. Barnes Nov 25 '10 at 19:06
  • Yes, you can nest interfaces in Java. 'public static interface Func {...}' etc. – Affe Nov 25 '10 at 19:12
  • @Affe: A PITA indeed. Unless your "_getTest" function is pretty large it almost doesn't seem worth the effort since you end up writing so much extra code for the functors. Although I'll bet that the functor version is faster since the compiled, optimized code is probably allot smaller. – Robert S. Barnes Nov 25 '10 at 20:53
2

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.

Mariy
  • 5,746
  • 4
  • 40
  • 57
2

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.)

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
1

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.

cadolphs
  • 9,014
  • 1
  • 24
  • 41
0

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;   
gpeche
  • 21,974
  • 5
  • 38
  • 51