2017-05-23 2 views
0

ジェネリックを学ぶことを試みています。CardDeckのようなものです。Tに互換性のない境界があります - Javaジェネリック

Card.java

package com.tn.deck; 

public class Card<S extends Comparable<S>, R extends Comparable<R>> implements Comparable<Card<S, R>> { 
    private S suit; 
    private R rank; 

    public Card(S suit, R rank) { 
     this.suit = suit; 
     this.rank = rank; 
    } 

    @Override 
    public String toString() { 
     return "Card{" + 
       "suit=" + suit + 
       ", rank=" + rank + 
       '}'; 
    } 

    @Override 
    public int compareTo(Card<S, R> o) { 
     return rank.compareTo(o.rank); 
    } 
} 

Deck.java

package com.tn.deck; 

import java.util.Arrays; 
import java.util.Collection; 
import java.util.Collections; 
import java.util.List; 
import java.util.stream.Collectors; 
import java.util.stream.IntStream; 


public final class Deck<T extends Card> { 
    private List<T> deck; 

    public <S extends Comparable<S>, R extends Comparable<R>> Deck(int numberOfDecks, S[] suits, R[] ranks) { 
     this.deck = initializeDecks(numberOfDecks, suits, ranks); 
     shuffle(); 
    } 


    private <S extends Comparable<S>, R extends Comparable<R>> List<T> initializeDecks(S[] suits, R[] ranks) { 
     return Arrays.stream(suits) 
       .flatMap(suit -> Arrays.stream(ranks).map(rank -> new Card<>(suit, rank))) 
       .collect(Collectors.toList()); // === It complains here. === 
    } 

    private <S extends Comparable<S>, R extends Comparable<R>> List<T> initializeDecks(int numberOfDecks, S[] suits, R[] ranks) { 
     return IntStream.range(0, numberOfDecks) 
       .mapToObj(i -> initializeDecks(suits, ranks)) 
       .flatMap(Collection::stream) 
       .collect(Collectors.toList()); 
    } 

    public void shuffle() { 
     Collections.shuffle(deck); 
    } 

    @Override 
    public String toString() { 
     return "Deck{" + 
       "deck=" + deck + 
       '}'; 
    } 
} 

私が手にエラーがそれはおそらく私だけがジェネリックを理解していない

Error:(57, 25) java: incompatible types: inference variable T has incompatible bounds 
    equality constraints: T 
    lower bounds: com.tn.deck.Card<S,R> 

ですが、私本当に私が間違っていることを誰かに説明してください。

+0

価値があるのは、どちらのクラスも実際にジェネリックを使用するべきではないということです。 – GriffeyDog

+0

@GriffeyDogこれは主に学習目的のためです。 –

+0

複数のスーツタイプと複数のランクタイプがありますか?具体的な 'Card 'タイプの 'S'と' R'の代わりに使える、あなたが書いた、または使用しようとしているタイプは?ジェネリックスは、命令ではなく型に関するアサーションです。あなたのタイプアサーションは 'Card 'または 'Card 'を許します。どうやってそれらを扱いますか? –

答えて

1

これは、Cardを作成していますが、List<T>を返す必要があるためです。 Tは、Cardではなく、Cardの任意のサブタイプです。

ジェネリッククラスを使用しており、T(またはジェネリックタイプを消去したもの)の新しいインスタンスを作成する必要がある場合は、そのようにできるファクトリを受け入れる必要があります。例:

public <S extends Comparable<S>, R extends Comparable<R>> Deck(int numberOfDecks, S[] suits, R[] ranks, BiFunction<S, R, T> cardFactory) { 
    this.deck = initializeDecks(numberOfDecks, suits, ranks, cardFactory); 
    shuffle(); 
} 


private <S extends Comparable<S>, R extends Comparable<R>> List<T> initializeDecks(S[] suits, R[] ranks, BiFunction<S, R, T> cardFactory) { 
    return Arrays.stream(suits) 
      .flatMap(suit -> Arrays.stream(ranks).map(rank -> cardFactory.apply(suit, rank))) 
      .collect(Collectors.toList()); 
} 

private <S extends Comparable<S>, R extends Comparable<R>> List<T> initializeDecks(int numberOfDecks, S[] suits, R[] ranks, BiFunction<S, R, T> cardFactory) { 
    return IntStream.range(0, numberOfDecks) 
      .mapToObj(i -> initializeDecks(suits, ranks, cardFactory)) 
      .flatMap(Collection::stream) 
      .collect(Collectors.toList()); 
} 
+0

以前は 'BiFunctions'を使用していませんでした。間違いなくそれを与えるだろう。 –

+0

@ Nilzone-、 'BiFunction'は、2つの引数を受け取り、値を返す関数を宣言する単なる抽象メソッドインタフェース(SAMインタフェース)です。関数インタフェース、 'Function'、' Supplier'、 'Consumer'も参照してください。 –

1

このエラーはなぜ発生しますか?汎用パラメータT extends Cardは、それ自身を含むCardのサブクラスのすべてがここで許可されます。汎用パラメータTがサブクラスタイプCardである場合、コードinitializeDecksがキャストせずにスーパークラスインスタンスを返そうとするとエラーが発生します。のは、簡単な具体例を見てみましょう:

class Superclass{} 
class Subclass extends Superclass{} 

Subclass sub= ...; 
// you can assign subclass's instance to superclass since it is-a superclass 
Superclass sup = sub; 
// you can assign superclass's instance to subclass you need casting it down 
Subclass sub2 = (Superclass) sup; 

あなたは以下のようにコードを修正することができます:エラーを取得しています方法で

<S extends Comparable<S>, R extends Comparable<R>> 
     List<? super T> initializeDecks(...){ 
    .... 
} 
1

を、あなたはCard<S, R>オブジェクトの束を作成して置くことをしようとしていますそれらをListに変換します。そのためには、Listはそのタイプのオブジェクトを保持できる必要があります。

List<T>は、オブジェクトのクラスがTまたはサブクラスがTの場合に限り、オブジェクトを保持できます。したがって、この行が機能するには、Card<S, R>Tのサブクラスでなければなりません。ここでTの制約を見ると、TCardのサブクラスであることが指定されています。この制約は、リストにカードを置く必要があるという関係を保証するものではないため、エラーが発生します。

関連する問題