簡體   English   中英

使用方法參數超類的接口實現

[英]Interface implementation with method argument superclasses

作為本主題中一般問題的一個實際例子,我想在Set接口中實現containsAll方法

public boolean containsAll(Iterable<?> c) { /* ... */ }

我認為這應該是允許的,因為CollectionIterable意味着這樣的containsAll將覆蓋接口要求。 同樣,更普遍的是能夠實現與參數超類的接口似乎應該工作。

然而,Eclipse說沒辦法(沒有試過直接javac) - 有人可以解釋原因嗎? 我確信規范中的某些內容使其成為現實,但我也想了解需求的動機。 或者我錯過了像Iterable<?>這樣的東西不是Collection<?>的超類?

作為一個附帶問題 - 鑒於我正在聲明兩種方法,帶有Iterable簽名的方法在使用Collection參數的調用時總是首選嗎?

Eclipse錯誤:

如果我使用Collection簽名刪除該方法,只需離開Iterable (請參閱錯誤后),我會得到以下內容:

The type BitPowerSet must implement the inherited abstract method Set<Long>.containsAll(Collection<?>)

確切的實施是:

@Override public boolean containsAll(Collection<?> c) {
  for (Object o : c) if (!contains(o)) return false;
  return true;
}
public boolean containsAll(Iterable<?> c) {
  for (Object o : c) if (!contains(o)) return false;
  return true;
}

由於您正在實現的接口聲明(abstract)方法containsAll(Collection<?>) ,因此必須使用此精確簽名實現它。 Java不允許您使用比原始參數類型更寬的參數類型來實現/覆蓋方法。 這就是當您使用Collection簽名注釋掉方法時出現錯誤的原因。

當沒有注釋掉該方法時,您沒有顯示您聲稱獲得的其他錯誤,但我想它可能需要對模糊方法重載執行某些操作。

我猜測為什么java有這個限制,比如你有:

class A {
    void foo(String s) { ...  }
}

class B extends A {
    // Note generalized type
    @Override void foo(Object s) { ...  }
}

現在,如果你有class C extends B並且它想要覆蓋foo ,那么它不清楚應該采用什么參數。

例如,首先直接說C擴展A,重寫void foo(String s) ,然后將其更改為擴展B.在這種情況下,C的現有foo覆蓋將變為無效,因為B的foo應該能夠處理所有Object ,不僅僅是String

參數類型是方法簽名的一部分,因此jvm需要一個具有完全相同簽名的方法來查找覆蓋。 containsAll(Iterable)將具有與containsAll(Collection)不同的簽名。

如果我沒記錯的話,編譯器必須使用一些變通方法來使泛型工作盡管有這種限制。

對於第二個問題,編譯器更喜歡Collection參數,因為它是Iterable的子類型,這使得Collection方法比Iterable更具體。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM