可以修改示例以返回值吗?

时间:2013-04-22 18:24:55

标签: java clojure

鉴于来自JNotify的以下示例,我在理解 implements 时遇到了一些麻烦。 class Listner实现JNotifyListener的方法 - fileRenamedfileModified等是否是有效的Java语法 - 但是将返回类型从void修改为Integer?

我想在JNotify之上编写一个Clojure库,并在未来使用Clojure代码块,直到Listener的一个方法返回。

  class Listener implements JNotifyListener {
    public void fileRenamed(int wd, String rootPath, String oldName,
        String newName) {
      print("renamed " + rootPath + " : " + oldName + " -> " + newName);
    }
    public void fileModified(int wd, String rootPath, String name) {
      print("modified " + rootPath + " : " + name);
    }
    public void fileDeleted(int wd, String rootPath, String name) {
      print("deleted " + rootPath + " : " + name);
    }
    public void fileCreated(int wd, String rootPath, String name) {
      print("created " + rootPath + " : " + name);
    }
    void print(String msg) {
      System.err.println(msg);
    }
  }

3 个答案:

答案 0 :(得分:3)

没有。实现签名中的返回值类型必须与它实现的接口的返回值类型匹配,具有完全匹配或实现/扩展类型。


对评论的回应(不是原始问题)

interface I {
  A foo();
}
class A {}
class B extends A {}
class C implements I {
  public B foo() { return null; }
}

Java 6编译器接受上面的代码,这意味着返回值在覆盖时间是协变的,因此评论者是正确的,匹配不一定是准确的。

答案 1 :(得分:3)

回应OP澄清的意见:

是的,这是Observer模式的一个简单示例:

public interface JNotifyListener {

    void fileRenamed(int wd, String rootPath, String oldName, String newName);

    void fileModified(int wd, String rootPath, String name);

    void fileDeleted(int wd, String rootPath, String name);

    void fileCreated(int wd, String rootPath, String name);
}

public enum Type {

    RENAMED,
    MODIFIED,
    DELETED,
    CREATED;
}

public class FileChangeEvent {

    final Type type;
    final int wd;
    final String rootPath;
    final String name;
    final String newName;

    public FileChangeEvent(Type type, int wd, String rootPath, String name, String newName) {
        this.type = type;
        this.wd = wd;
        this.rootPath = rootPath;
        this.name = name;
        this.newName = newName;
    }

    public FileChangeEvent(Type type, int wd, String rootPath, String name) {
        this(type, wd, rootPath, name, null);
    }

    public int getWd() {
        return wd;
    }

    public String getRootPath() {
        return rootPath;
    }

    public String getName() {
        return name;
    }

    public String getNewName() {
        return newName;
    }
}

public interface FileChangeEventListener {

    void notify(FileChangeEvent fileChangeEvent);
}

public class FileChangeEventNotifyer implements JNotifyListener {

    final Collection<FileChangeEventListener> listeners = new ConcurrentLinkedQueue<FileChangeEventListener>();

    @Override
    public void fileRenamed(int wd, String rootPath, String oldName, String newName) {
        notifyAll(new FileChangeEvent(Type.RENAMED, wd, rootPath, oldName, newName));
    }

    @Override
    public void fileModified(int wd, String rootPath, String name) {
        notifyAll(new FileChangeEvent(Type.MODIFIED, wd, rootPath, name));
    }

    @Override
    public void fileDeleted(int wd, String rootPath, String name) {
        notifyAll(new FileChangeEvent(Type.DELETED, wd, rootPath, name));
    }

    @Override
    public void fileCreated(int wd, String rootPath, String name) {
        notifyAll(new FileChangeEvent(Type.CREATED, wd, rootPath, name));
    }

    private void notifyAll(final FileChangeEvent changeEvent) {
        for (final FileChangeEventListener changeEventListener : listeners) {
            changeEventListener.notify(changeEvent);
        }
    }

    public void registerListener(final FileChangeEventListener eventListener) {
        listeners.add(eventListener);
    }

    public void unregisterListener(final FileChangeEventListener eventListener) {
        listeners.remove(eventListener);
    }
}

您可以看到class只需要实施FileChangeEventListener并注明其对主FileChangeEventNotifyer的兴趣。然后它将使用事件调用其notify方法。

这里有一些常见的陷阱。一个是该实现不使用synchronized,因此如果一个类在事件发生时被注册,则它可能会错过通知。优点是这是非阻塞的。因此,您需要确定是否更喜欢使用非阻塞集合或阻止集合。

此外,您需要确保之后注册的任何已注册的侦听器都未注册,否则它们会堆积起来并最终导致内存泄漏。

我已将其实现为具有FileChangeEvent的单个Type - 显然您可以拥有父FileChangeEvent类,然后使用类的子类扩展它。这又取决于你的需求。

无论如何,这应该让你开始。

答案 2 :(得分:0)

从Clojure方面考虑使用promise / deliver而不是future。然后,监听器中的方法可以实现承诺。 http://clojuredocs.org/clojure_core/clojure.core/promise

如果这是一个库,最好传递一个函数而不是使用future或promise。这将允许库的用户传入他们自己的闭包,而不必引入另一个线程更改。