2017-11-15 27 views
1

Javaでどちらかのモナドを実装したいと思います。 次のコードでエラーが発生しますErasure of method Either(V) is the same as another method in type Either<T,V> TとVが同じタイプに消去されてエラーが発生することはありません。コレクションなしでジェネリックスを使用するときの型消去エラー

public class Either<T, V> { 
    private T t; 
    private V v; 

    public Either(T t) { 
     this.t = t; 
    } 

    public Either(V v) { 
     this.v = v; 
    } 
} 

関連の記事ではなく、重複:以下の記事は、2つのコンストラクタ、Collection<T>と1とCollection<V>で別の対処

。問題は、コンストラクタの両方のパラメータが型削除されてCollectionになるため、同じ型シグニチャがあることです。

プライマリタイプが異なるため、私の投稿は重複していません。

次のポストアドレス法、compareTo(Real r)と1とcompareTo(Object o)

と別の種類TVは関連はありませんので、私のポストは、重複しません少なくとも私が見ている方法ではない。

質問

  • なぜこのタイプの消去エラーが発生しますか。

  • JavaでEither monadを実装するにはどうすればこのエラーを解決できますか?

+0

私はこれは自己解答型の質問(これは問題ありません:)ですが、実際に質問にどこかの質問が含まれていると助かります... –

答えて

0

私の質問は、ジェネリック医薬品の風味を持っている以外どうやら、それは、Implementing Comparable, compareTo name clash: "have the same erasure, yet neither overrides the other"と同じ問題です。

ジェネリック型は実行時にObjectに変換されているため解決できません。 したがって、同じタイプの署名を持つpublic Either(T t) - >public Either(Object t)public Either(V v) - >public Either(Object v)です。

は1つが次の操作を行うことができ、問題を解決するには:あなたは、一般的なタイプのいずれかで Bounded Typesを使用することができる場合

public class Either<T, V> { 
    private T t; 
    private V v; 

    private Either(T t, V v) { 
     this.t = t; 
     this.v = v; 
    } 

    public static Either instaceOfT(T t) { 
     return new Either<>(t, null); 
    } 

    public static Either instaceOfV(V v) { 
     return new Either<>(null, v); 
    } 
} 
+1

誰かがそのようなクラスを開発しました。http:// www .functionaljava.org/javadoc/4.4/functionaljava/fj/data/Either.html。だからあなたは一見をして、彼らがそれをどのように実装したか見てみたいかもしれません。 –

+0

あなたはあなたの 'v'をそこに忘れてしまいました。 – Rogue

+0

私はコードをSOに直接書くよりもよく知っていたはずです。 よく見つかる –

0

、これは、消去の問題を克服します。しかし、私はほとんどの場合、そのようなクラスを制限するのは好きではなく、非常に一般的な方法で定義することで、どこでも再利用できることを理解しています。

public class Either<T extends String, V extends Object> { 

private T t; 
private V v; 

private Either(T t, V v) { 
    this.t = t; 
    this.v = v; 
} 

public static <T extends String, V extends Object> Either<T, V> either(T t) { 
    return new Either<T, V>(t, null); 
} 

public static <T extends String, V extends Object> Either<T, V> either(V v) { 
    return new Either<T, V>(null, v); 
} 

} 
0

あなたは各コンストラクタに、異なるタイプの2番目のパラメータを導入する可能性およびJavaはそれで罰金になります。今この二番目のパラメータとして使用することができるので

public class Either<T, V> { 
    public enum Left { Left } 
    public enum Right { Right } 
    private T t; 
    private V v; 

    public Either(T t, Left l) { 
     this.t = t; 
    } 

    public Either(V v, Right r) { 
     this.v = v; 
    } 
} 

これは、合理的です弁別器。私を襲った何

Javaのも、このコードでを呼び出すためにどのコンストラクタ推測する完全にできたことを発見しました:だから

new Either<Integer,Exception>(new Integer(2),null); 
    new Either<Integer,Exception>(new Exception(),null); 

、なぜそれがどちらかの方法の消去(そんなにうるさいされていましたV)はタイプの別の方法と同じです最初の場所ですか?知りません。

私が知っていることは、常に無駄な引数をコンストラクタに渡す必要がないということです。だから私は、Javaを使用してこの問題を回避するに頼っ可変引数:もちろん

public class Either<T, V> { 
    public enum Left { Left } 
    public enum Right { Right } 
    private T t; 
    private V v; 

    public Either(T t, Left... l) { 
     this.t = t; 
    } 

    public Either(V v, Right... r) { 
     this.v = v; 
    } 
} 

、今、あなたはこのようなコンストラクタを呼び出すことができます。

new Either<Integer,Exception>(new Integer(2),null); 
    new Either<Integer,Exception>(new Exception(),null,Right,nul); 

をそして、私は私の知る限り「ドンとしてそれに反対しないだろうあなたのコードを読む必要があります。
しかし、利点は、あなたが今、このようなあなたのいずれかのインスタンスを構築することができるということです。
https://github.com/fejnartal/Either-JavaType

0

どちらもTおよびV:あなたは、このタイプの完全な、不変実装を見つけることができます

new Either<Integer,Exception>(new Integer(2)); 
    new Either<Integer,Exception>(2); 
    new Either<Integer,Exception>(new Exception()); 

コンパイル時に2つのコンストラクタの型シグネチャが同じになるように、型名はObjectになります。

効果的なJavaの助言に従うことで、これを避けることができます。過負荷を慎重に使用し、静的なファクトリメソッドをパブリックコンストラクタに優先します。

public class Either<T, V> { 
    private T t; 
    private V v; 

    private Either(T t, V v) { 
     this.t = t; 
     this.v = v; 
    } 

    public static <L, R> Either<L, R> left(L leftValue) { 
     return new Either(leftValue, null); 
    } 

    public static <L, R> Either<L, R> right(R rightValue) { 
     return new Either(null, rightValue); 
    } 
} 

通常、同じ数の引数を持つメソッドオーバーロードは、特にジェネリックの面であいまいさを招きます。それらを避け、異なる名前のメソッドを公開することで、コンパイラとAPIのユーザーを幸せに保つことができます。

関連する問題