現在、グリッドのような構造の操作を処理できる抽象コードで作業しています。具体的なメソッドの代わりに、ラムダ式を受け取り、グリッド要素間の方向性関係に基づいて機能を提供するフレームワークを開発しようとしています。これらのメソッドにジェネリック型を返そうとすると問題に遭遇しました。一般的な戻り値の型とラムダ関数の引数
私は、特定の方向のグリッド要素を見つけるラムダ関数と各要素のいくつかのメソッドを実行するコンシューマを受け入れる以下のような作業メソッドを持っています。代わりに、このメソッドが呼び出されるたびに、要素発見機能を渡しするので、私はそのような機能が宣言され、にforEachClockwiseメソッドをオーバーロードしているインタフェースの直交」を持っていいだろうことを決めた
public static <E> void forEachClockwise(Direction d, Function<Direction, ? extends E> f, Consumer<? super E> c){
/*For each of the orthogonal directions, in order:*/
c.accept(f.apply(d));
/*end For*/
}
このインタフェースの要素を受け入れます。
public static <O extends Orthogonal> void forEachClockwise(Direction d, O center, Consumer<O> c){
forEachClockwise(d, center::findNextByDirection, c);
}
私はここでジェネリックを使用し、Consumerメソッドがキャストせずにグリッド要素のフィールドにアクセスできるように宣言しました。私はこれが設計の選択肢が貧弱であることを心配しています。私が作成した直交インターフェースとテストクラスは、いくつかの異なることを試しても警告なしでキャストなしでコンパイルされていないためです。私が試したfindNextByDirectionの
public interface Orthogonal {
public <E extends Orthogonal> E findNextByDirection(Direction a);
}
2 '有効' の実装は以下のとおりです。
/* in Coordinate implements Orthogonal: */
@Override
public <E extends Orthogonal> E findNextByDirection(Direction a) {
return (E) (/*The proper Coordinate*/);
}
そして
最適@Override
public Coordinate findNextByDirection(Direction a) {
return /*The proper Coordinate*/;
}
//Warning on return type declaration:
/*Type safety: The return type Element for findNextByDirection(Direction) from the type Element needs unchecked conversion to conform to E from the type Orthogonal*/
、私はforEachClockwise方法を持っていると思います(と他のメソッド)が受け入れることができます。これは、キャストせずに、それを呼び出す同じクラスの要素を返します。座標のfindNextByDirectionは座標を返し、Addressはアドレスを返し、CellはCellを返します。その他の質問と回答ここでは、一般的な戻り値の型を持つメソッドを作る方法を説明しますが、見つけませんでしたこの種のメソッドをラムダパラメータとして使用する方法に関するヒント。
私がまだ試していないことは、いくつかの種類の直交性と方向性を引数として受け入れる新しいfindByDirectionメソッドを作成することです。あるいは、ForEachClockwiseメソッドをOrthogonalで定義されたいくつかのメソッドで呼び出すことです。私が試みたことのように。他のアプローチは、インターフェイスに独自のジェネリック型を与えることですが、明らかに間違っていて、すべての直交クラスを "MyClassが直交を実装する"と宣言するのは妥当ではありません。
このインターフェイスを完全に設計しましたかジェネリックが彼らが設計されていないことをやろうとしていることを期待していますか?または、クラスを取得して正しいメソッドを呼び出し、それ自体の型の要素を総称的に返す簡単な方法がありますか?
全コード:
package test;
import java.util.function.Consumer;
import java.util.function.Function;
public enum Direction {
NORTH, EAST, SOUTH, WEST;
public static <O extends Orthogonal> void forEachClockwise(Direction d, O center, Consumer<O> c){
forEachClockwise(d, center::findNextByDirection, c);
}
public static <X> void forEachClockwise(Direction d, Function<Direction, ? extends X> f, Consumer<? super X> c){
c.accept(f.apply(d));
forEachExcept(d, f, c);
}
public static <X> void forEachExcept(Direction d, Function<Direction, ? extends X> f, Consumer<? super X> c){
for(int i=0; i<3; i++){
d = Direction.getClockwise(d);
c.accept(f.apply(d));
}
}
public static Direction getClockwise(Direction d){
switch(d){
case EAST:
return SOUTH;
case NORTH:
return EAST;
case SOUTH:
return WEST;
case WEST:
return NORTH;
default:
return null;
}
}
}
interface Orthogonal {
public <E extends Orthogonal> E findNextByDirection(Direction a);
}
class Coordinate implements Orthogonal{
int x;
int y;
public Coordinate(int x, int y){
this.x = x;
this.y = y;
}
public int getX(){
return x;
}
public int getY() {
return y;
}
@Override //Warning on "Coordinate" below. Compiler suggests writing
//entire <E extends Orthogonal> method signature
public Coordinate findNextByDirection(Direction a) {
switch(a){
case NORTH:
return new Coordinate(x+1, y);
case SOUTH:
return new Coordinate(x-1, y);
case EAST:
return new Coordinate(x, y+1);
case WEST:
return new Coordinate(x, y-1);
default:
return null;
}
}
}
(警告付きで)コンパイルする完全な例を作成できれば役に立ちます。例えば、この実装は警告なしでコンパイルします。 'public class Elementは直交{ @Overrideを実装します。public Element findNextByDirection(Direction a){ これを返します。要素からEに準拠するように未チェックの変換を必要とするタイプからfindNextByDirectionの戻り値の型の要素(ディレクション): 」型の安全性:スニペット } } ' – assylias
は私、戻り値の型宣言要素のための警告でコンパイルしませんOrthogonal型の " –
"を返しましたか? – assylias