简体   繁体   English

在java中传递和强制执行成员函数

[英]passing and enforcing a member function in java

I'm trying to create a work queue class (FooQueue) that has: 我正在尝试创建一个工作队列类(FooQueue),它具有:

  • a set of function members doing work (do*). 一组功能成员在做工作(做*)。 Each one of them take one parameter, having the same type (FooItem). 它们中的每一个都采用一个具有相同类型的参数(FooItem)。
  • an 'add' function that takes 2 parameters: one of the above functions, and a FooItem. 一个'add'函数,它接受2个参数:上述函数之一和FooItem。 Most importantly, the add function should only be able to take in a member function of the FooQueue class, rather than a member function of another class with the similar signature 最重要的是,add函数应该只能接受FooQueue类的成员函数,而不是具有类似签名的另一个类的成员函数

The code compiles when the do function is static, but not when the function is non-static, even though acording to this the definition of the instance function member is correct. 当do函数是静态的时,代码编译,但是当函数是非静态的时,代码编译,即使根据这个 ,实例函数成员的定义是正确的。

What should be changed to make it compile/run? 应该改变什么来使其编译/运行?

public class App {
    public static void main( String[] args ) {
        FooQueue q = new FooQueue();
        q.add( FooQueue::dos, new FooItem() );    // this compiles
        q.add( q::do1, new FooItem() );           // this does not:
                                                  // does not consider q::do1 'delegate'
                                                  // as taking 2 parameters,
                                                  // with q being the first one
        FooQueue q2 = new FooQueue2();
        q.add( FooQueue2::dos, new FooItem() );   // want this to give compiler error
        q.add( FooQueue2::do1, new FooItem() );   // want this to give compiler error
    }
}

public class FooQueue {
    public static void dos( FooQueue q, FooItem item ) {
        System.out.println( "FooQueue:sdo" );
    }
    public void do1( FooItem item ) {
        System.out.println( "FooQueue:do1" );
    }
    public void add( java.util.function.BiConsumer<FooQueue,FooItem> func, FooItem wi ) {
        System.out.println( "FooQueue:addWorkItem2" );
        func.accept( this, wi );
    }
}
public class FooItem {
}
public class FooQueue2 {
    public static void dos( FooQueue2 q2, FooItem item ) {
        System.out.println( "FooQueue2:sdo" );
    }
    public void do1( FooItem item ) {
        System.out.println( "FooQueue2:do1" );
    }
}

It's not related to static / non-static method, nor generics, but only to BiConsumer definition. 它与静态/非静态方法无关,也与泛型无关,只与BiConsumer定义有关。

BiConsumer requires two parameters, so you need lambda that requires two parameters and doesn't return any. BiConsumer需要两个参数,因此您需要需要两个参数且不返回任何参数的lambda。

To fix that, use instance method reference : 要解决此问题,请使用实例方法引用

FooQueue q = new FooQueue();
q.add(FooQueue::do1, new FooItem());

Don't confuse it with static method reference. 不要将它与静态方法引用混淆。 FooQueue::do1 is syntatic sugar for lambda: FooQueue::do1是lambda的FooQueue::do1糖:

(qInstance, item) -> qInstance.do1(item));

This approach allows you to accept only methods from FooQueue . 此方法允许您仅接受来自FooQueue方法。

Note that q:do1 is not compatible with BiConsumer as it's converted to: 请注意, q:do1BiConsumer不兼容,因为它转换为:

(item) -> q.do1(item)

Read more about Instance method reference 阅读有关Instance方法参考的更多信息


Full example with different classes 不同类的完整示例

public class App {
    public static void main(String[] args) {
        FooQueue q = new FooQueue();
        FooQueue2 q2 = new FooQueue2();

        q.add(FooQueue::do1, new FooItem());
        // Equals to:
        q.add((qInstance, item) -> qInstance.do1(item), new FooItem());

        // q.add(FooQueue2::do1, new FooItem());  // not compile
    }
}

class FooQueue {
    void do1(FooItem item) {
        System.out.println("FooQueue:do1");
    }

    void add(BiConsumer<FooQueue, FooItem> func, FooItem wi) {
        System.out.println("FooQueue:addWorkItem");
        func.accept(this, wi);
    }
}

// class that pretends to be FooQueue
class FooQueue2 {
    void do1(FooItem item) {
        System.out.println("FooQueue2:do1");
    }
}

class FooItem {
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM