匿名内部类:他们什么时候适合?

问题描述:

以下面的例子。有一个我想使用的对象,称它为DoodadDoodad元素对浏览器事件的处理效果很差。典型的Doodad实例化将是Doodad someDoodad = new Doodad();。很明显,这不适合我的需求,因为糟糕的事件处理。是不是适合我重写onBrowserEvent()方法,像这样:匿名内部类:他们什么时候适合?

Doodad someDoodad = new Doodad() { 
@Override 
    public void onBrowserEvent(Event event) { 
     switch (DOM.eventGetType(event)) { 
      case Event.ONDBLCLICK: 
      case Event.ONFOCUS: 
      case Event.ONCLICK: 
       if (!isEnabled()) { 
        return; 
       } 
       break; 
     } 
     super.onBrowserEvent(event); 
    } 
}; 

显然,这是一个简单的例子,但是当我可能不会希望使用匿名内部类?它是否被明确禁止或不可能?

我看到很多第一个问题的答案,但目前为止的答案都没有回答第二个问题:是否明确地禁止或不可能使用匿名内部类?

+0

像上面的例子,大部分是我在事件处理案例中看到的。 –

通常,匿名内部类的最佳用法是当您只想创建此类的特定实现的一个实例时。而且实现非常简单。理想情况下,它应该包含1-2行代码。你的方法onBrowserEvent()比2行更长。

+1

为了公平起见,OP使用switch语句而不是if语句将2行变为6。 – corsiKa

+0

@glowcoder它是6行来说明问题:什么时候适合使用匿名内部类。我可以用两行完成同样的事情,但希望看到与代码长度(实际用法)以及功能用法有关的答案。 –

+0

我更喜欢将方法添加到枚举中。在这种情况下,我会定义方法'proceedBrowserEvent'并为每个枚举成员实现它。在这种情况下,监听器应该真的调用一个方法,所以它将是一行。 – AlexR

我的看法:

匿名内部类:回调从一个功能(这样你就不会写代码的两倍)

命名的内部类:回调从几个函数(或者,你只需要一个类对于父类的内部逻辑)

通常情况下,事件侦听器是一段不是非常通用的代码,但与特定的小部件,按钮,文本字段等无关。在这种情况下,代码不需要适当地公开以供世界重用。定义它在何处使用就更容易了,这就是匿名内部类的用途。它们允许在另一种方法中快速嵌入代码段,而不必担心类名称,包,可见性或可重用性。

当然,你可以用匿名内部类来做什么,总是可以用适当的独立类来完成。但是当你的事件处理类足够通用时(可以处理大量事件),可重用的,有状态的,或者当从代码中提取事件管理代码有一些好处时,这样做更有意义定义事件生成元素。

我不确定我明白你的问题,我希望这条信息能帮助你找到答案。不要犹豫提出进一步的问题。

匿名内部类是创建闭包的Java语法。这里有一个近似的例子:

interface Adder { 
    int add(int arg); 
} 

... 

Adder createAdder(int n) { 
    final int nf = n; 
    return new Adder() { 
     int add(int arg) { return arg + nf; } 
    } 
} 

方法createAdder创建本质上是一个函数,使用闭包捕获传递的值n。功能编程正在试图使其成为主流,关闭是非常重要的。这就是为什么大家都尖叫我们需要Java中的“真正”关闭(即大多数语法比我的例子更好)。 (当然,我并没有回答所问的问题,我想我的意思是匿名课程对我上面描述的很有帮助。几乎所有我会创建一个命名的内部类,因为如果任何名称是自我记录,并在我看来更容易阅读)

+2

真正的关闭不会要求捕获变量标记为最终... – gizmo

+0

是的,你需要手动捕获它们的事实很糟糕,但它只是语法上的,而不是功能上的缺陷。 –

我会建议匿名类,当它实现一种方法和/或是半满屏幕。

如果匿名非代码段的代码具有命名类恕我直言。

+0

“糟糕的事件处理”是什么意思? –

+0

在OP中,我提到“Doodads的事件处理能力很差。”假设它在“禁用”时不正确地处理点击。 –

+0

该类是否被命名或匿名对它的行为没有影响(除了默认的'toString'),如果它具有'糟糕的事件处理',如果它被命名,它仍然会有这个。 –

当只包含非常少量的代码时,我只使用匿名内部类。原因在于IMO混淆了代码并使其不易读。

如果需要更多的代码,我希望创建一个新的类,扩展基类(在这种情况下,“装饰物()”

+0

定义“非常少量的代码”... –

+0

你的例子对我来说可以,但除此之外,我倾向于创建一个单独的类。 –

在您的例子,你想创建一个单独的类。这是因为你忽略了这个方法的原因,也就是说,对浏览器事件的处理很差。

具体来说,你可能想要在几个不同的地方创建这些改进的Doodads。在未来更新和改进?你会想要删除所有这些改进的Doodads并使用正确的实现。试图找到你所有的匿名Doodads可能是烦人的或棘手的。而如果你有一个单独命名的类然后重构此类将很容易。

此外,如果您为它创建单独的类,则您改进Doodad的原因可以是自记录。而如果你只有一个匿名类,那么你将不得不写评论或者让未来的维护者猜测你为什么完成了你所做的事情。

例如。类似于封闭

public class ImprovedBrowserEventHandlingDoodad extends Doodad { 
    ... 
} 

任何通常是使用匿名类

如一个很好的候选人。

new Thread(new Runnable() { 
    @Override 
    public void run() { 
     doSomething(); 
    } 
}).start(); 

你只想做一些在这其中某些特定情况下,没有必要复制和粘贴代码别的地方或将其重构为一个方法。

GUI的事件处理程序在使用匿名类时很常见,因为它们的使用仅限于GUI的设计方式,并且不需要在使用它的特定组件外创建单独的事件处理程序实例。例如,当您将鼠标悬停在滚动条上时,其外观通常会更改。程序中没有其他任何东西会导致这种变化,通常事件处理程序会有两行告诉滚动条改变其外观,例如。 scrollbar.setMouseOverEffect(true);