2014-03-29 46 views
1

NOTE:我知道这是危险地接近许多其他问题。然而,我没有看到任何特别与Android的OnClickListener接口有关的东西。我在一般意义上问。通过匿名类扩展接口VS实例化

我明白通过一个匿名类... 一拉实例化一个接口的区别:和扩展接口

private final Runnable runnable = new Runnable() { 
    @Override 
    public void run() { 
     draw(); 
    } 

}; 

...。

public class ClassyClass implements Runnable { 
    ... 
    //do other cool stuff here 
    ... 
    @Override 
    public void run() { 
     draw(); 
    } 
    ... 
    //and more here 
    ... 

} 

但是,除了从诸如OnClickListener接口的明显好处是有很强的优势,以任一选项?

我认为扩展它将是明显的选择,因为您已经创建了该对象 - 不需要重复工作。这是正确的吗?

我问在一般意义上,但是,因为我目前Runnable工作,如果它已经从任一选项我很想知道看到一个优势。

回答

2

那么这里是显示的主要差别的例子。这有点做作,但只是为了说明。

下面是一个匿名版本:

class PrintBuilder { 
    List<Runnable> printers = new LinkedList<>(); 

    List<Runnable> get() { 
     return printers; 
    } 

    PrintBuilder add(final String line) { 
     printers.add(new Runnable() { 
      public void run() { 
       System.out.println(line); 
      } 
     }); 

     return this; 
    } 
} 

这里是一个嵌套的版本:

class PrintBuilder { 
    List<Printer> printers = new LinkedList<>(); 

    PrintBuilder add(String line) { 
     printers.add(new Printer(line)); 
     return this; 
    } 

    List<Printer> get() { 
     return printers; 
    } 

    static class Printer implements Runnable { 
     String line; 

     Printer(String line) { 
      this.line = line; 
     } 

     public void run() { 
      System.out.println(line); 
     } 
    } 
} 

所以,你可以看到主要的区别是,则:

  • 匿名类是内部,它有一个隐式引用封闭的实例。

特别是,在上面的例子中,PrintBuilder被泄漏,直到内部Runnable对象死亡。在第二个例子中,Runnable类是静态的,所以它没有这个问题。

  • 匿名类短一点。

匿名类不需要字段和构造函数,因为它们是隐式的。

  • 代码组织方式的巨大差异。

一个匿名类被声明在实例化的地方,如果匿名类不是非常短,这对封闭类的布局可能具有相当的破坏性。另一方面,如果匿名类很短,功能类语法就很好。

同样所有的课程都会增长,以我的经验,当匿名课程变得太大时,这会变成一种气味。匿名类更难以重构到顶级类。

+0

非常感谢。我赞赏具体的赞成/反对。最后一个问题。我有点得到它,我已经看到其他人谈论泄漏(在前1),但你能具体解释为什么它发生? – BrassApparatus

+1

@BrassApparatus:发生这种情况的原因是,内部类通过设计隐式引用其封闭对象,以便能够访问其字段和方法。就像在第二个示例的打印机中有一个PrintBuilder字段,并将'this'作为Printer构造函数的参数传递。 –

+0

@JBNizet陷阱,谢谢。我感谢所有的帮助。 – BrassApparatus

0

第一个片段定义了一个没有名字的类,它实现了Runnable接口(并实例化了匿名类)。第二个定义了一个具有名称的类,该类还实现了Runnable接口。

在继承和接口实现方面没有区别,除了第二个类有一个名称,第一个没有名称。

第二个代码片段允许多个类实例化Runnable实现,而第一个代码段定义一个只能从其封闭类中知道的类。有时候一个更好,有时另一个更好。

0

这两种方法都是有效的。使用哪一个取决于你的用法:

  • 如果你在另一个类中实现一个接口,你将有权访问父类的protected和private方法。
  • 如果您想保持事物分离并重复使用此接口的相同实现,则创建一个单独的类是一种可行的方法。