2017-03-13 4 views
3

私はジェネリックスに新しく、必要な情報を提供しようとしている小さなプログラムでそれらを使用しようとしたときに、次の問題が発生しました。メソッド引数の汎用型変換が不可能な理由は何ですか?

私は必要なものだけを提供しようとしますが、欠けているものがあれば、私に知らせて、必要なものを提供します。

最初のものは、次のインタフェースである。

1: public interface IPrice<T extends IPrice<T>> { 
2:  void setPriceToZero(); 
3:  T addPrice(T price); 
4:  T subtractPrice(T price); 
5:  T multiplyPriceByFactor(int factor); 
6:  String priceToString(); 
7: } 

それがクラスBnSPriceによって実装されます。ここでの、おそらく必要な部分:

1: public class BnSPrice implements IPrice<BnSPrice> { 
2:  public BnSPrice subtractPrice(BnSPrice price) {...} 
2: } 

今の部分はコンパイルされませんこれは、私は本当に理解しない:私は何を得る

1: public static void main(String[] args){ 
2:  [...] 
3:  IPrice<? extends BnSPrice> test = new BnSPrice(5); 
4:  test.subtractPrice(new BnSPrice(5)); 
5:  [...] 
6: } 

"Error:(27, 28) java: incompatible types: main.bnsCalculatorModel.BnSPrice >cannot be converted to capture#1 of ? extends >main.bnsCalculatorModel.BnSPrice"

です私が減算法を呼び出す行で。

なぜこのようなことが起こりますか、これを修正して、まだインターフェイスにプログラムできるようにするにはどうすればよいですか?

(私の目標は、将来的には他の「物価の種類」で私のプログラムを拡張することは容易でなければならないということである。)

+0

行番号を追加してください!エラーが行の 'IPrice <? BnSPrice> test = new BnSPrice(5); '?を拡張します。 – Pyranja

+0

[ジェネリック型が引数に適用できない理由は、両方のスーパークラスを拡張する理由?](http://stackoverflow.com/questions/21452966/why-generic-type-is-not-applicable-for-argument-extends -super-class-for-both) –

+0

行番号が追加されました。コードブロック3行目にエラーがありました。説明にSweeperはいい仕事をしました。 – Wolfone

答えて

6

まずは、この作品を作る方法を見てみましょう:

IPrice<BnSPrice> test = new BnSPrice(5); 
test.subtractPrice(new BnSPrice(5)); 

わかりましたので、ワイルドカードに? extends ...作品を取り除きます。どうして?

一般的なワイルドカードの概念を理解する必要があります。 <? extends BnPrice>は、これがBnPriceのサブクラスである任意のタイプであることを意味します。現時点では、あなたは何も持っていませんが、私の主旨を示すために作成しましょう。

class MyPrice extends BnPrice {} 

あなたがタイプMyPriceの変数にBnPriceオブジェクトを割り当てることはできません注意してください。

素晴らしい!今度は私たちのtestオブジェクトがあります。あなたはそれがBnPriceまたはMyPriceすることができBnPriceすなわち、任意のサブクラスであることができ<? extends BnPrice>Tを書いたので

T subtractPrice(T price); 

:さんはsubtractPriceがタイプIPrice<? extends BnPrice>に定義されている方法を見てみましょう。TBnPriceある場合、これはコンパイルします:

test.subtractPrice(new BnSPrice(5)); 

あなたがBnPriceを期待する方法にBnPriceを渡しています。すべての良い。 しかし、,Tは、必ずしもBnPriceである必要はありません。 MyPriceも同様です。もしそれがMyPriceだったら? MyPriceパラメータにBnPriceを渡すことができないため、上記の行はコンパイルされません。

このパラメータは、BnPriceを拡張する任意の型であるため、BnPriceを渡すことはできません。

+0

それは私にとってはある程度意味があります。あなたのサンプルの型がMyPriceかBnSPriceかどうかをコンパイラが知りませんでした。私たちがインターフェースを使って作った契約が十分でない理由を理解するのはちょっと難しいですが、私はそれが私の特殊なケースでは十分であるが一般的ではないというあいまいな考えを持っています。 1つのサブタイプに存在するが、他のサブタイプには存在しないメソッドを呼び出そうとしている可能性があります。私は正しい方向に考えていますか?ああ、1つのフォローアップの質問:あなたの最初のコードブロックは私が得ることができる最も一般的なバージョンですか? – Wolfone

+0

@ウォルフォーネ私はあなたが正しい方向に考えていると思います、そして確かに私が懸念している限り、あなたが得ることができる最も一般的なバージョンです。 – Sweeper

+0

いいです、完璧です。ご協力ありがとうございました! – Wolfone

0

テストの種類はIPrice<? extends BnSPrice>あるので、減算の引数の予想されるタイプなのでBnSPriceではなく? extends BnSPriceです。

これは、コンパイルします:

BnSPrice test = new BnSPrice(5); 
test.subtractPrice(new BnSPrice(5)); 
関連する問題