扩展接口与通过匿名类实例化

时间:2014-03-29 08:45:45

标签: java interface runnable anonymous-class

NOTE:我知道这很危险地接近许多其他问题。但是,我还没有看到任何与Android的OnClickListener界面无关的内容。我是一般意义上的问题。

我理解通过匿名类实例化接口之间的区别...... la:

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合作,如果它看到任何一种选择的优势,我很乐意知道。

3 个答案:

答案 0 :(得分: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类是静态的,因此它不会出现此问题。

  • 匿名课程有点短。

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

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

匿名类在它被实例化的地方被声明,如果匿名类不是很短,这对封闭类的布局非常具有破坏性。另一方面,如果匿名类很短,那么类似函数的语法就很好了。

此外,所有课程都会增长,根据我的经验,当匿名课程变得太大时,这可能会变成一种气味。匿名类也很难重构到顶级类。

答案 1 :(得分:0)

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

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

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

答案 2 :(得分:0)

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

  • 如果在另一个类中实现接口,则可以访问父类的protected和private方法。
  • 如果您希望保持分离并为此接口重用相同的实现,则可以创建单独的类。