2015-04-24 123 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(); 
    } 
} 

是否有可能以某種方式,除了方式我將參數傳遞給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

對不起,我忘了一些東西 - 如果我需要在main中使用方法doSomething(),我必須明確地實現它,對嗎?或者有其他方法嗎? E:用不同的話說,如果我想讓C實現相同的接口 – tcigler

+0

@tcigler是的,你要麼實現/包裝doSomething(),要麼爲foo提供一個getter。 – 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(); 
    } 
} 

就個人而言,我覺得這是一個清晰,實現移動你正在嘗試做的靈活方式。