2015-04-24 4 views
2

У меня есть несколько классов, которые реализуют некоторый интерфейс. Теперь я хочу создать новый класс, который может расширить один из них, на основе расчета времени выполнения, используя методы интерфейсов. Давайте поговорим в коде:Java расширяет общий прототип

public interface Interface { 
    public void doSomething(); 
} 

public class A implements Interface { 
    @Override 
    public void doSomething() { 
     System.out.println("hello"); 
    } 
} 

public class B implements Interface { 
    @Override 
    public void doSomething() { 
     System.out.println("hi"); 
    } 
} 

Это существующие классы, так что теперь мне нужно сделать что-то вроде этого (который не работает, конечно):

public class C<T extends Interface> extends T { 
    public void doSomethingElse() { 
     this.doSomething(); 
    } 

    public static void main(String[] args) { 
     C c; 
     if(isSomethingLoaded) { 
      c = new C<A>(); 
     } else { 
      c = new C<B>(); 
     } 
     c.doSomethingElse(); 
    } 
} 

возможно ли это как-то, кроме пути что я передаю аргумент Interface other в конструктор C и сохраняю свойство класса.?

ответ

6

Класс не может распространяться на его параметр типа.

Использование композиции вместо наследования:

public class C<T extends Interface> { 
    private final T foo; 

    public C(T foo){ 
     this.foo = foo; 
    } 

    public void doSomethingElse() { 
     foo.doSomething(); 
    } 

    public static void main(String[] args) { 
     C<?> c; 
     if(isSomethingLoaded) { 
      c = new C<>(new A()); 
     } else { 
      c = new C<>(new B()); 
     } 
     c.doSomethingElse(); 
    } 
} 

Вы можете даже не нужен параметр типа здесь, а просто использовать тип интерфейса в качестве аргумента типа/члена.

+0

Извините, я кое-что забыл. Если мне нужно использовать метод doSomething() в основном, я должен явно реализовать его, правильно? Или есть другой путь? E: другими словами, если я хочу, чтобы C реализовал такой же интерфейс – tcigler

+0

@tcigler Да, у вас есть либо реализовать/wrap doSomething(), либо предоставить getter для foo. – Puce

2

Я думаю, что это такие ситуации, которые показывают, почему у нас есть правило предпочтительной композиции над наследованием. Рассмотрим решение с использованием композиции:

public class Test { 
    public interface Interface { 
     void doSomething(); 
    } 

    public static class A implements Interface { 
     @Override 
     public void doSomething() { 
      System.out.println("Doing A"); 
     } 
    } 

    public static class B implements Interface { 
     @Override 
     public void doSomething() { 
      System.out.println("Doing B"); 
     } 
    } 

    public static class C implements Interface { 
     private Interface composedWith; 

     public C(Interface i) { 
      this.composedWith = i; 
     } 

     @Override 
     public void doSomething() { 
      this.composedWith.doSomething(); 
     } 
    } 

    public static void main(String[] args) { 
     C c; 
     if(isSomethingLoaded) { 
      c = new C(new A()); 
     } else { 
      c = new C(new B()); 
     } 
     c.doSomething(); 
    } 
} 

Лично я считаю, что это понятнее и двигаться гибкий способ достижения того, что вы пытаетесь сделать.

Смежные вопросы