Внедрение двух интерфейсов в анонимном классе
У меня есть два интерфейса:
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();
}
Это избавит вас от выполнения декларации класса на уровне класса или верхнего уровня.
Результат называется локальный класс. Локальные классы, объявленные в методах экземпляра, также являются внутренними классами, что означает, что они могут ссылаться на экземпляр содержащегося объекта.