Внедрение двух интерфейсов в анонимном классе

У меня есть два интерфейса:

interface A {
    void foo();
}

interface B {
    void bar();
}

Я могу создать анонимные экземпляры классов, реализующих один из этих интерфейсов:

new A() {
    void foo() {}
}

или

new B() {
    void bar() {}
}

Я хочу создать анонимный класс, который реализует оба интерфейса. Что-то вроде (фиктивное):

new A implements B {
    void foo() {}
    void bar() {}
}

Это, очевидно, дает ошибку компиляции: "B не может быть разрешен для типа".

Обходной путь довольно прост:

class Aggregate implements A, B {
    void foo() {}
    void bar() {}
}

Затем я использую Aggregate, где бы я ни использовал анонимный класс.

Мне было интересно, хотя для анонимного класса даже законно реализовать два интерфейса.

Ответ 1

"Анонимный внутренний класс может распространять один подкласс или реализовывать один интерфейс. В отличие от не анонимных классов (внутренних или иных), анонимных внутренний класс не может обойти оба. Другими словами, он не может как расширить класс, так и реализовать интерфейс и не может реализовывать более одного интерфейса. "(http://scjp.wikidot.com/nested-classes)

Ответ 2

Если вы решили сделать это, вы можете объявить третий интерфейс, C:

public interface C extends A, B {
}

Таким образом, вы можете объявить один анонимный внутренний класс, который представляет собой реализацию C.

Полный пример может выглядеть так:

public class MyClass {

  public interface A {
    void foo();
  }

  public interface B {
    void bar();
  }

  public interface C extends A, B {
    void baz();
  }

  public void doIt(C c) {
    c.foo();
    c.bar();
    c.baz();
  }

  public static void main(String[] args) {
    MyClass mc = new MyClass();

    mc.doIt(new C() {
      @Override
      public void foo() {
        System.out.println("foo()");
      }

      @Override
      public void bar() {
        System.out.println("bar()");
      }

      @Override
      public void baz() {
        System.out.println("baz()");
      }
    });
  }

}

Результат этого примера:

foo()
bar()
baz()

Ответ 3

Для сохранения некоторых нажатий клавиш (например, если интерфейсы имеют множество методов), вы можете использовать

abstract class Aggregate implements A,B{
}

new MyObject extends Aggregate{
   void foo(){}
   void bar(){}
}

Обратите внимание, что ключ должен объявить агрегат как абстрактный

Ответ 4

Обратите внимание, что вы можете создать именованный локальный класс, реализующий два интерфейса:

void method() {
    class Aggregate implements A, B {
        void foo() {}
        void bar() {}
    }

    A a = new Aggregate();
    B b = new Aggregate();
}

Это избавит вас от выполнения декларации класса на уровне класса или верхнего уровня.

Результат называется локальный класс. Локальные классы, объявленные в методах экземпляра, также являются внутренними классами, что означает, что они могут ссылаться на экземпляр содержащегося объекта.