Java中是不是存在用于满足接口的空方法的习语?

Posted

技术标签:

【中文标题】Java中是不是存在用于满足接口的空方法的习语?【英文标题】:Is there an idiom in Java for empty methods which exist to satisfy an interface?Java中是否存在用于满足接口的空方法的习语? 【发布时间】:2010-10-27 10:11:37 【问题描述】:

假设我有一个类Foo 实现了一个接口,例如MouseListenerMouseListener 接口包含五个方法,但我只想覆盖其中一个(mouseClicked())。是否有一种标准的惯用方式来格式化其他方法?

我的倾向是写以下内容:

@Override
public void mouseClicked(MouseEvent e) 
    // (...) <-- actual code here


@Override
public void mouseEntered(MouseEvent e) 
    // Do nothing.  Exists to satisfy MouseListener interface.


@Override
public void mouseExited(MouseEvent e) 
    // Do nothing.  Exists to satisfy MouseListener interface.


@Override
public void mousePressed(MouseEvent e) 
    // Do nothing.  Exists to satisfy MouseListener interface.


@Override
public void mouseReleased(MouseEvent e) 
    // Do nothing.  Exists to satisfy MouseListener interface.

我很喜欢明确表示方法是有意留白而不是意外留白,但我并不热衷于放弃所有的垂直空间,基本上什么都没有。我还看到了以下格式:

public void mouseClicked(MouseEvent e) 
    // (...) <-- actual code here


public void mouseEntered(MouseEvent e) 
public void mouseExited(MouseEvent e) 
public void mousePressed(MouseEvent e) 
public void mouseReleased(MouseEvent e) 

我对此一般没问题,我理解作者的意图,但是当添加 (recommended) @Override 注释时,它变得非常丑陋。

我不是一个特别有经验的 Java 编码器,所以我想我会问是否有约定。想法?

【问题讨论】:

您知道 MouseAdapter 类,对吧? java.sun.com/javase/6/docs/api/java/awt/event/MouseAdapter.html 【参考方案1】:

在这种特殊情况下,您应该遵循 wilums2 的建议并扩展 MouseAdapter 而不是实现 MouseListener。这些适配器类的目的是让您在仅实现接口的某些方法时不必提供空实现。

更一般地说,简短的回答是“不”,没有关于如何记录空方法的标准约定,尽管我通常使用类似的东西

@Override
void foo() 
  // No implementation necessary

【讨论】:

【参考方案2】:

我的做法和你一样,如果一行里什么都没有。也许在一大堆“实现单行”之上发表评论。

【讨论】:

【参考方案3】:

使用鼠标适配器

【讨论】:

虽然这个答案是正确的,但它并没有解决问题的精神,即当只实现部分接口时要做什么。 他要求的是conevtions,而不是要实现什么接口。 扩展此类以创建 MouseEvent 侦听器并覆盖感兴趣事件的方法。 (如果你实现了 MouseListener 接口,你必须定义其中的所有方法。这个抽象类为它们都定义了 null 方法,所以你只需要为你关心的事件定义方法。)java.sun.com/j2se/1.4.2/docs/api/java/awt/event/… MouseAdapter 的来源将是一个很好的约定。但是,我认为这取决于方法。对于 MouseListener,无需说明您是否提供了实现。对于其他接口,抛出异常可能是合适的,而在其他接口中,只记录该方法没有做任何事情可能是合适的。【参考方案4】:

一般来说,您所说的是空对象模式的扩展。您正在定义一个 Null 对象并仅通过覆盖您关心的方法来扩展它。

作为自动化方法的示例,在我的 JavaDude Bean Annotations (http://code.google.com/p/javadude/wiki/Annotations) 中,您可以执行以下操作。 [注意:我不建议对 MouseListener 执行此操作,因为 MouseAdapter 已经存在,您可以将其子类化...以下对于您只想实现一些选择方法的其他大型接口很有用]

@Bean(nullObjectImplementations = @NullObject(type=MouseListener.class))
public class MyMouseHandler extends MyMouseHandlerGen 
    public void mouseClicked(MouseEvent e) 
        // your handling of a MouseClick
    

然后您可以使用 MyMouseHandler 来处理点击。=

注意:对于 JRE/JDK 中的类名称,MouseAdapter 是一个真的错误选择。它不是 GoF 适配器模式的一个实例;它实际上是 MouseListener 的 Null Object 实现。

顺便说一句:您可以将 @Override 与方法声明放在同一行 - 对于您的示例,您可以拥有

@Override public void mousePressed(MouseEvent e)  /* not needed */ 
// et al

【讨论】:

【参考方案5】:

有几种方法可以做到这一点。 Oracle java conventions p6.4(第 11 页)说空方法应该看起来像

public void empty() 

还有一篇Steve Yohanan 写于 2003 年 ant 的文件,上面写着

public void empty()


虽然我还没有找到“作为接口存根的空方法”的任何约定。 因此,作为结论,没有标准化的方法来做到这一点。 有些人喜欢留下评论,有些人喜欢单行,有些人喜欢用空白正文写成任何其他方法。

【讨论】:

感谢您实际提供指向 OP 所要求的编码约定的链接。【参考方案6】:

MouseAdapter 非常适合这种特定情况,而 Adapter 习惯用法通常也很棒。适配器具有接口的所有方法的空实现,允许您子类化并仅实现与您的类相关的那些方法。正如 Andrew Hare 建议的那样,适配器也可以抛出 NotImplementedException。

【讨论】:

【参考方案7】:

侦听器的目的是通知某些事件。如果侦听器接口包含的方法回调比您需要的多,那么只需忽略您不关心的那些。在您的情况下,MouseAdapter 就是为此目的而设计的。请不要抛出UnsupportedOperationException,因为调用者很可能不会期待异常。它也很可能违反了侦听器接口的约定,因为每个方法都需要实现。

【讨论】:

调用者也可能不期望函数什么都不做。如果什么都不做,你就违反了接口契约,这将导致奇怪且极难调试的错误。我会说抛出错误,以便在测试/使用期间立即出现问题。如果你不能抛出错误,你至少应该记录一个不支持的操作被调用的警告。什么都不做,可能是一个代价高昂的错误(及时调试产生的错误)。 (如果有疑问,至少记录它,以便至少有一个很好的提示它导致的错误)【参考方案8】:

我想我会将其描述为“无操作实现”或使用“适配器”一词。正如其他人所指出的,Java 提供了一个 MouseAdapter 类,它可以满足您的需求。严格来说,它并不完全属于适配器模式的定义,它将一种 API 转换为另一种,但坦率地说,我倾向于务实地命名这些东西。

可能最重要的事情是明确您打算让该方法没有实现。在MouseAdapter 的特定情况下,您可能不想到处乱扔UnsupportedOperationException,但总的来说,这可能是一个很好的信号,表明您不打算提供实现。通常需要在源代码(或者更好的方法文档)中添加注释来解释为什么您没有完全实现接口。

【讨论】:

【参考方案9】:

我认为这并不特别重要。就我个人的喜好而言,我不喜欢在开口旁边看到右大括号,这给出了:

public void mouseEntered(MouseEvent e) 

有点空,但还好。在返回值的情况下,我们可以使它看起来一致,这是 [] 样式所没有的。

但是当谈到循环中的罕见情况时,我喜欢其中的分号:

// Made up example.
while (++i < len && str.charAt(i) != '\0') 
    ;

这会给:

public void mouseEntered(MouseEvent e) 
    ;

catch 子句的情况下,你最好在评论中有一个很好的借口(也许放弃一个中断)。

【讨论】:

【参考方案10】:

我在搜索这个确切的问题时发现了这个。我在需要 onScrollStateChanged 而不是 onScroll 的地方使用滚动。我倾向于:

@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
            int totalItemCount) 
    return;         
 

但是,我喜欢您给出的第二个示例(在同一行带有大括号)。它紧凑而干净,可以始终如一地表达故意留空的想法。

编辑:这是我决定的:

@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
            int totalItemCount) return;

这个有很多参数,所以它看起来不像一行那么好,但你明白了。

【讨论】:

以上是关于Java中是不是存在用于满足接口的空方法的习语?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 `while ((ch = getchar()) != EOF)` 是常见的习语? [关闭]

函数式编程:将列表划分为给定大小的较小列表的习语?

您从经验中学到了哪些与 C++ 相关的习语、误解和陷阱?

pythonrequests模块初探

python+requests实现接口测试 - get与post请求使用

Requests库介绍