简体   繁体   English

Java中是否有使用方法引用JAVA重写方法的简短形式?

[英]Is there any short-form for overriding methods in Java with method references JAVA?

I keep having situations where this would be really handy 我一直有这样的情况会非常方便

component.addWindowListener() { new WindowListener() {
        // quick overriding to make syntax less verbose
        windowClosing(e) -> Foo::doFoo;

        windowActivated(e) -> Foo::doFoo;
    }
}

currently this would mostly look like this: 目前这大部分看起来像这样:

component.addWindowListener() new WindowListener() {
    @Override
    public void windowClosing(WindowEvent e) {
        Foo.doFoo(e);
    }

    @Override
    public void windowActivated(WindowEvent e) {
        Foo.doFoo(e);
    }
}

Where the method reference points to some function: 方法参考指向某些功能:

public static void doFoo(WindowEvent e) {
    // does code
}

Is anything like this possible? 有可能这样吗? because the whole overriding of non-functional interfaces is quite quite frustrating. 因为非功能性接口的整个覆盖非常令人沮丧。

There is no such language feature, but if you have to implement an interface so often that this verbosity becomes relevant, you can write your own adapter. 没有这样的语言功能,但是如果你必须经常实现一个接口以使这种详细程度变得相关,你可以编写自己的适配器。

Eg, with the adapter below, you could write 例如,使用下面的适配器,你可以写

f.addWindowListener(WindowAdapter.window()
    .onClosing(ev -> ev.getWindow().dispose())
    .onClosed(ev -> System.out.println("closed"))
);

or utilizing the power of import static : 或利用import static的力量:

f.addWindowListener(window().onClosing(ev -> System.out.println("closing")));

so, to stay with your example 所以,坚持你的榜样

f.addWindowListener(window().onClosing(Foo::doFoo).onActivated(Foo::doFoo));

Adapter: 适配器:

public class WindowAdapter implements WindowListener {
    static Consumer<WindowEvent> NO_OP = ev -> {};
    public static WindowAdapter window() {
        return new WindowAdapter(NO_OP, NO_OP, NO_OP, NO_OP, NO_OP, NO_OP, NO_OP);
    }
    final Consumer<WindowEvent> opened, closing, closed,
        iconified, deiconified, activated, deactivated;

    public WindowAdapter(Consumer<WindowEvent> opened, Consumer<WindowEvent> closing,
        Consumer<WindowEvent> closed, Consumer<WindowEvent> iconified,
        Consumer<WindowEvent> deiconified, Consumer<WindowEvent> activated,
        Consumer<WindowEvent> deactivated) {
        this.opened = opened;
        this.closing = closing;
        this.closed = closed;
        this.iconified = iconified;
        this.deiconified = deiconified;
        this.activated = activated;
        this.deactivated = deactivated;
    }
    public WindowAdapter onOpened(Consumer<WindowEvent> c) {
        Objects.requireNonNull(c);
        return new WindowAdapter(opened==NO_OP? c: opened.andThen(c),
            closing, closed, iconified, deiconified, activated, deactivated);
    }
    public WindowAdapter onClosing(Consumer<WindowEvent> c) {
        Objects.requireNonNull(c);
        return new WindowAdapter(opened, closing==NO_OP? c: closing.andThen(c),
            closed, iconified, deiconified, activated, deactivated);
    }
    public WindowAdapter onClosed(Consumer<WindowEvent> c) {
        Objects.requireNonNull(c);
        return new WindowAdapter(opened, closing, closed==NO_OP? c: closed.andThen(c),
            iconified, deiconified, activated, deactivated);
    }
    public WindowAdapter onIconified(Consumer<WindowEvent> c) {
        Objects.requireNonNull(c);
        return new WindowAdapter(opened, closing, closed,
          iconified==NO_OP? c: iconified.andThen(c), deiconified, activated, deactivated);
    }
    public WindowAdapter onDeiconified(Consumer<WindowEvent> c) {
        Objects.requireNonNull(c);
        return new WindowAdapter(opened, closing, closed, iconified,
            deiconified==NO_OP? c: deiconified.andThen(c), activated, deactivated);
    }
    public WindowAdapter onActivated(Consumer<WindowEvent> c) {
        Objects.requireNonNull(c);
        return new WindowAdapter(opened, closing, closed, iconified,
            deiconified, activated==NO_OP? c: activated.andThen(c), deactivated);
    }
    public WindowAdapter onDeactivated(Consumer<WindowEvent> c) {
        Objects.requireNonNull(c);
        return new WindowAdapter(opened, closing, closed, iconified,
            deiconified, activated, deactivated==NO_OP? c: deactivated.andThen(c));
    }
    @Override public void windowOpened(WindowEvent e) { opened.accept(e); }
    @Override public void windowClosing(WindowEvent e) { closing.accept(e); }
    @Override public void windowClosed(WindowEvent e) { closed.accept(e); }
    @Override public void windowIconified(WindowEvent e) { iconified.accept(e); }
    @Override public void windowDeiconified(WindowEvent e) { deiconified.accept(e); }
    @Override public void windowActivated(WindowEvent e) { activated.accept(e); }
    @Override public void windowDeactivated(WindowEvent e) { deactivated.accept(e); }
}

Building on top of Holger's idea , here is an implementation that is a bit simpler. 建立在Holger的想法之上,这是一个更简单的实现。 The API is a bit different but you could easily add all the on*() methods if you like: API有点不同但如果您愿意,可以轻松添加所有on*()方法:

public class WindowListenerAdapter implements WindowListener {
    private Map<Integer, Consumer<WindowEvent>> listeners = new HashMap<>();

    public static WindowListenerAdapter adapter() {
        return new WindowListenerAdapter();
    }

    public WindowListenerAdapter register(int eventId, Consumer<WindowEvent> listener) {
        if (eventId < WindowEvent.WINDOW_FIRST || eventId > WindowEvent.WINDOW_LAST) {
            throw new IllegalArgumentException("Invalid event id: " + eventId);
        }
        listeners.merge(eventId, listener, Consumer::andThen);
        return this;
    }

    private void processEvent(WindowEvent e) {
        listeners.getOrDefault(e.getID(), i -> {}).accept(e);
    }

    @Override
    public void windowOpened(final WindowEvent e) {
        processEvent(e);
    }

    @Override
    public void windowClosing(final WindowEvent e) {
        processEvent(e);
    }

    @Override
    public void windowClosed(final WindowEvent e) {
        processEvent(e);
    }

    @Override
    public void windowIconified(final WindowEvent e) {
        processEvent(e);
    }

    @Override
    public void windowDeiconified(final WindowEvent e) {
        processEvent(e);
    }

    @Override
    public void windowActivated(final WindowEvent e) {
        processEvent(e);
    }

    @Override
    public void windowDeactivated(final WindowEvent e) {
        processEvent(e);
    }
}

and use it as: 并将其用作:

f.addWindowListener(adapter().register(WINDOW_CLOSING, Foo::doFoo)
        .register(WINDOW_ACTIVATED, Foo::doFoo));

You could maybe even add a 你甚至可以添加一个

public static WindowListenerAdapter forWindow(Window f) {
    final WindowListenerAdapter adapter = adapter();
    f.addWindowListener(adapter);
    return adapter;
}

and use it as: 并将其用作:

forWindow(f).register(WINDOW_CLOSING, Foo::doFoo)
        .register(WINDOW_ACTIVATED, Foo::doFoo);

or similarly with 或类似的

public WindowListenerAdapter on(Window w) {
    w.addWindowListener(this);
    return this;
}

write: 写:

adapter().register(WINDOW_CLOSING, Foo::doFoo)
        .register(WINDOW_ACTIVATED, Foo::doFoo)
        .on(f);

You could write your own class to hold these lambdas and call them as needed. 您可以编写自己的类来保存这些lambda并根据需要调用它们。 If you do this a lot it might save some code, but in your example you could end up with more lines of code in total. 如果你这么做很多,它可能会节省一些代码,但在你的例子中,你可能会得到更多的代码行。

Is there any short-form for overriding methods in Java with method references ? Java中是否有使用方法引用覆盖方法的简短形式?

Looking at JEP draft: Concise Method Bodies maybe there will be something like that: 看看JEP草案:简明方法机构可能会有类似的东西:

    component.addWindowListener(new WindowListener() {
        public void windowClosing(e) -> Foo.doFoo(e);
        public void windowActivated(e) -> Foo.doFoo(e);
    });

and

    component.addWindowListener(new WindowListener() {
        public void windowClosing(e) = Foo::doFoo;
        public void windowActivated(e) = Foo::doFoo;
    });

The uses the syntax to show how 使用语法来说明如何

Concise method bodies avoid the line noise, and let you treat the anonymous class almost like a family of lambdas: 简洁的方法体避免了线路噪声,让你几乎像一个lambda系列一样对待匿名类:

The first code uses labda expressions . 第一个代码使用labda表达式 The second code uses the requested method references . 第二个代码使用请求的方法引用

While this is not a solution yet it may become one. 虽然这不是一个解决方案,但它可能会变成一个。 Let's stay tuned. 让我们保持关注。

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

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