2017-11-30 4 views
0

私はボードをモデリングしています。可能な限り一般的なものにしたいと思っていました。Java Generics:Java 2D汎用配列のこの例でのキャストを避けるにはどうすればよいですか?

また、私のコードは今のところ完全に動作していますが、Cellクラスの作業を開始してすぐに問題があることがわかります。

Cell.java

public class Cell<T> { 
    private t value; 

    public Cell(T value) { 
     this.value = value; 
    } 

    // setters and getters 
} 

Board.java

import java.lang.reflect.Array; 

public abstract class Board<T, E extends Cell<T>> { 
    protected E[][] cells; 

    protected Board(Class<? extends E> c) { 
     cells = (E[][])Array.newInstance(c, 6, 7); 
    } 

    protected void resetBoard(T resteVal) { 
     for (int i = 0; i < cells.length; i++) 
      for (int j = 0; j < cells[i].length; j++) 
       cells[i][j]= (E) new Cell<T>(); //HERE IS THE QUESTION 
    } 
} 

Game.java

public interface Game { 
    boolean islegalMove(); 
    boolean isWin(); 
    void move(); 
    void resetGame(); 
    void getScore(); 
} 

Connect4.java

public class Connect4<E extends Cell<Integer>> extends Board<Integer,E> implements Game { 
    public Connect4(Class<? extends E> c) { 
     super(c); 
    } 

    // override methods 
} 

答えて

1

は、私は問題はアーキテクチャであると思いprotected Cell<T>[][] cells;

public abstract class Board<T, E extends Cell<T>> { 
    protected Cell<T>[][] cells; 
    @SuppressWarnings("unchecked") 
    public Board(Class<? extends E> c) { 
     cells = (E[][])Array.newInstance(c, 6, 7); 
    } 

    protected void resetBoard(T resteVal) { 
     for (int i = 0; i < cells.length; i++) { 
      for (int j = 0; j < cells[i].length; j++) { 
       Cell<T> cell = new Cell<T>(); 
       cell.setValue(resteVal); 
       cells[i][j] = cell; //HERE IS MY REPLACEMENT 
      } 
     } 
    } 
} 
+0

core probleは正しいアーキテクチャではありません(クラスキャストは正確にそれについて述べています)。これはこの問題の正しい修正ではありません。 –

+0

何を手に入れませんでしたか? – Ele

+0

問題は、この場合、Cellクラスを継承するクラスにアクセスすることができず、これはEを意味のないものにします。 –

1

ことで、このprotected E[][] cells;を交換してください。

Cell<T>クラスを定義しています(拡張可能など)。

次に、カスタムCellで動作する抽象的なBoardを定義します。

public abstract class Board<T, E extends Cell<T>> { 
    // why do not use T[][] cells instead? 
    protected final E[][] cells; 

    protected Board(E[][] cells) { 
     this.cells = cells; 
    } 

    // we hole Cell instances inside this class, so no need to create new ones 
    protected void resetBoard(T resetVal) { 
     for (int i = 0; i < cells.length; i++) 
      for (int j = 0; j < cells[i].length; j++) 
       cells[i][j].setValue(resetVal); 
    } 
} 

そして最後に、我々は具体的なセルインスタンスコンクリートボードをdefeineことができます。

public final class MagicBoard<T> extends Board<T, MagicBoard.MagicCell<T>> { 

    public MagicBoard(Supplier<MagicCell<T>> supplier) { 
     //noinspection rawtypes,unchecked 
     super(new MagicCell[6][7]); 
    } 

    public static final class MagicCell<T> extends Cell<T> { } 
} 

再開:

  1. 抽象クラスBoardは、具体的なセルインスタンスが作成についてウェアべきではありません。最大、それは子供のクラスからSupplierを受け入れて、この作品を具体的なクラス 'MagicBoard'に委譲することができます(このクラスだけがどのタイプのCellを作成すべきか知っています)。

  2. 無駄を避けるようにしてください。Cellインスタンス作成中です。 Boardの中に入れておけば、それを共有しないでください。それを再利用してください。値をリセットするだけです。

  3. 質問!私はコード全体を知りませんが、Cellに値が1つしかない場合は、Cellを使用せず、protected final T[][] cells;を使用することができます(BoardにはCellのすべてのロジックが含まれている必要がありますが、単純な価値を保つだけです)。しかし、これは私の意見です。

+0

上記のセルクラスは単なる例であり、多くのクラスがそれを使用し、それらの属性とメソッドを持っているので、私のコードでそれを持つ必要があると思います!私がT細胞ではなかった理由は、簡単にCellクラスを拡張し、新しい細胞で私のボードを操作することができるので、Connect4クラスを見てください! –