4

我是安卓新手。我在基本的面向对象编程课程中学习过接口为类提供了一种增强其功能的方法。实际上以这种方式增强其功能的类,实现这些接口并覆盖所有用接口编写的方法。

以下代码在 Android 中执行相同的工作:

public class MyActivity extends Activity implements OnClickListener {
   // All other code you may expect

   myButton.setOnClickListener(this);

   @override
   public onClick(View view) {
      // Code when view is clicked
   }
} 

这段代码是可以理解的。但是下面的代码对我来说毫无意义,我已经在不同的地方搜索了它,但没有得到满意的答案。

public class MyActivity extends Activity {
   // All other code you may expect

   myButton.setOnClickListener(new OnClickListner() {

      @override
      public onClick(View view) {
         // Code when view is clicked
      }
  });
}

现在,OnClickListener()是 Android 文档中所说的接口,现在我们正在实例化一个接口。不是只实现接口吗?请帮助我理解这一点。

4

4 回答 4

12

new OnClickListner() {不是实例化接口,而是声明一个 匿名内部类。基本上是一个匿名类(实现接口 OnClickListner 的类),它本身没有名称。

文档

匿名类表达式包括以下内容:

  • 新运营商
  • 要实现的接口或要扩展的类的名称。在此示例中,匿名类正在实现接口 OnClickListner。
  • 包含构造函数参数的括号,就像普通的类实例创建表达式一样。注意:在实现接口的情况下,没有构造函数,所以你使用一对空括号,就像在这个例子中一样。
  • 一个主体,它是一个类声明主体。更具体地说,在正文中,允许方法声明,但不允许声明。
于 2013-03-26T15:52:48.907 回答
1

实际上,这是我在 OOP 中见过的最糟糕的做法之一,而不仅仅是 java。

基本上,您从 中创建一个匿名内部类Interface,并且您必须立即实现接口提供的所有方法。在这种情况下,将接口视为抽象类(基本上总是如此,或多或少)。

虽然广泛传播并得到某些语言的适当支持,但 java 仅在语言级别支持内部类的概念。然而,在字节码级别,没有内部类。编译器将这些内部类语言结构从它们的父类中分离出来,将它们作为兄弟姐妹放置在它们旁边,并带有一个 $ 符号和一个连续的数字,并将私有作用域元素(方法、变量)提升到包作用域。现在让它沉入一会儿,并考虑安全影响。

接下来的事情是,这些匿名内部类在 Android 上下文中被过度使用(最初的问题被标记为 Android)完全弄乱了代码并使其完全不可读。这与干净的代码相去甚远,我强烈建议遵循这一点,以维护易于阅读和维护的代码。

另一件事是每个人都会new Interface() { ... };自然地创建一个新对象。通常你会在 Android 世界的听众中看到这一点。如果您有多个侦听器,请为您自己和您的用户节省一些内存并使用开关实现一个对象...不要每次都创建一个新对象只是因为 Google 示例会这样做,并且因为有些人在此处回答时在他们的示例中这样做在 SO 和教程或论坛中。:)

于 2015-02-24T06:19:23.437 回答
1

那些 OnClickListener 是匿名类。括号包括类定义。

于 2013-03-26T15:53:39.397 回答
1

如果将 new 与接口一起使用,则必须在创建实现接口但没有自己的名称的匿名内部类{ }时覆盖Block 中接口提供的方法。

例如,这允许您拥有多个不同的单击处理程序,而无需创建一个为每个按钮实现 OnClickListner 的类。

于 2013-03-26T15:57:04.340 回答