代码之家  ›  专栏  ›  技术社区  ›  Robert S. Barnes Antoni

Java中是否有相当于C++成员函数指针?[副本]

  •  2
  • Robert S. Barnes Antoni  · 技术社区  · 14 年前

    在你成为笨蛋之前,是的,我见过 Function Pointers in Java ,不,它并没有真正回答我的问题,基本上是因为我对Java很陌生,所以我并没有真正理解答案的分配。

    这是一种有点混乱的Java/C++,在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;
        }
    }
    
    5 回复  |  直到 7 年前
        1
  •  8
  •   Affe    14 年前

    不,Java中根本没有函数这样的东西。只有对象和方法是完全由对象拥有并从属于它们的。目标是你的主和爪哇的主人,除了通过他的意志,什么都不会发生。

    您可以通过使对象实现委托接口来实现某种java委托,这是非常接近的。

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

    希望这足以让这个想法得到理解。一般来说,在应用程序代码中你看不到这一点。

    编辑:

    因为您是Java新手,所以语法实际上就是您要做的事情。这也可以说明它是一个什么样的皮塔,以及为什么人们不喜欢它:)

    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;
      }
    
    }
    
        2
  •  2
  •   Mariy    14 年前

    Java中的函数不是第一类对象。这意味着最好的方法是通过子类化或实现一个接口。接口将包含方法定义。然后您将实际传递一个具有所需方法的对象。例如,请参见Collection.sort的工作原理。

        3
  •  2
  •   Tom Hawtin - tackline    14 年前

    JDK8可以引入lambdas和方法引用。

    同时,匿名内部类提供了创建函子对象的稍微冗长的方法。

    public interface FooTest {
        boolean test(Foo foo);
    }
    [...]
        FooTest[] tests = {
             new FooTest() { public void boolean test(Foo foo) {
                 return foo.test1();
             }},
             [...]
        };
    

    对于构建类似的测试框架来说,反射或使用注释处理器生成静态代码是一种方法。(请注意,反射通常是有害的,但在测试框架等情况下是可以的。)

        4
  •  1
  •   cadolphs    14 年前

    在Java中不能指向函数,也没有直接的等价物。

    我唯一能想到的就是函数对象。你知道,在C++中,你会超载函数调用操作符,

    operator()
    

    在Java中,创建一个名为 Function 用虚拟方法 doSomething 然后,不再像在C中那样使用函数指针数组,而是使用 功能 对象 剂量测定 然后调用的方法。

        5
  •  0
  •   gpeche    14 年前

    考虑到不同语言的差异,将您的示例简单地翻译成Java。

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

    注意,在上面的例子中,PTMF不是线程安全的。对于线程安全实现,将PTMF更改为

    public class PTMF {
        public abstract boolean test(Foo self, Foo other);
    };
    

    或者,在这种情况下更好:

    public interface PTMF {
        boolean test(Foo self, Foo other);
    };
    

    环的主体 getTest() 将是:

    current = ptmf.test(current, _foos[ i ] ) ? _foos[ i ] : current;