2015-10-06 160 views
0

我無法編譯需要重寫使用泛型作爲其中一個參數的抽象類超類型的方法的方法。編譯器會抱怨擴展類的setRef()方法不會覆蓋超類型的方法。使用抽象類的泛型參數覆蓋方法

父抽象類:

public abstract class AbsClass<Q extends Interf> { 
    public abstract Ref<? extends AbsClass<Q>> getRef(); 
    public abstract <M extends AbsClass<Q>> void setRef(Ref<M> newRef); 
} 

裁判:

public interface Ref<M extends AbsClass<? extends Interf>> { } 

和INTERF是:

public interface Interf { } 

擴展子類(setRef()不編譯):

public class ChildClass extends AbsClass<InterfImpl> { 
    @Override 
    public Ref<ChildClass> getRef() { 
     return null; 
    } 

    @Override 
    public <M extends ChildClass> void setRef(Ref<M> newRef) { 
     return null; 
    } 
} 

我也試過使用通配符,並收到相同的錯誤。使用通配符,抽象類setRef()是:

public abstract void setRef(Ref<? extends AbsClass<Q>> newRef); 

和延伸類setRef()是:

public void setRef(Ref<ChildClass> newRef) 

甚至:

public void setRef(Ref<? extends ChildClass> newRef) 



的只有這樣才能讓它編譯的是,如果擴展類'setRef()使用抽象類「類型:

public <M extends AbsClass<Interf>> void setRef(Ref<M> newRef) 

但我想限制newRef參數的鍵入爲Ref<ChildClass>或子類型,所以這不是完美的。我如何讓我的擴展類只允許ChildClass或它的子類型爲setRef()方法的newRef參數?我的一部分困惑是ChildClass的getRef()返回值處理泛型輸入,並且setRef()參數上的相同「簽名」無法編譯。幫幫我?謝謝!

+1

請包括堆棧跟蹤。 –

+1

@Tim,他正在談論編譯時錯誤。 – Codebender

+0

正確,沒有堆棧跟蹤,只是編譯器錯誤:「ChildClass類型的方法setRef(Ref )必須覆蓋或實現超類型方法。」這是來自方法聲明的'public void setRef(Ref newRef)'形式。 –

回答

1

setRef的問題是,你可以通過AbsClass<? extends Interf>類型的變量訪問ChildClass一個實例,因此參數類型setRef會是什麼樣子<M extends AbsClass<? extends Interf>>而這又可能是任何M,但也不會因爲Q匹配<M extends AbsClass<Q>>已被定義爲InterfImpl你的情況。

你可以改變ChildClass這樣:

public <M extends AbsClass<InterfImpl>> void setRef(Ref<M> newRef) 

但這將仍然允許任何M,你不能只使用Ref<ChildClass>因爲我上面說的,即如果您使用AbsClass<InterfImpl>或甚至AbsClass<? extends InterfImpl>類型的變量,編譯器不會知道Ref<ChildClass>

只允許參數爲ChildClass的一種方法是在通用類型中也使用ChildClass,例如,像這樣:

public abstract class AbsClass<Q extends Interf, M extends AbsClass<Q, M>> { 
    public abstract Ref<M> getRef(); 
    public abstract void setRef(Ref<M> newRef); 
} 

public class ChildClass extends AbsClass<InterfImpl, ChildClass> { 

    public Ref<ChildClass> getRef() { return null; } 

    public void setRef(Ref<ChildClass> newRef) { } 
} 
+0

工程就像一個魅力!感謝您的快速和徹底的迴應! –

0

因爲在AbsClass.setRef(),你的參數類型Ref<? extends AbsClass<Q>>

的你得到一個錯誤,但在你的ChildClass.setRef()參數是Ref<? extends ChildClass>類型。

對於重寫,子類應該在方法中具有與父類相同的類型化參數(在使用泛型時進行類型刪除之前)。

+0

我想我理解,但是因爲ChildClass擴展AbsClass '不符合'<?在其父項中擴展了AbsClass >? –

+0

@BrianFrutchey問題是'<?擴展AbsClass >'可能匹配更多,編譯器不能將其縮小到'ChildClass'。 – Thomas