web-dev-qa-db-ja.com

Comparable、compareTo name clashの実装:「同じ消去がありますが、どちらも他方をオーバーライドしません」

Real(任意の大きさで正確な実数を処理するためのクラス[現時点で長さが2 ^ 31未満である限り])をとるcompareToメソッドと、をとるcompareToメソッドが欲しいのですが。オブジェクトですが、Javaは私を許可しておらず、その理由を知るのに十分な経験がありません。

Comparableを実装するようにクラスを変更しようとしたところ、以下のエラーメッセージが表示されました。エラーメッセージの意味はよくわかりませんが、作成するすべてのメソッドのさまざまなメソッドシグネチャを使用してクラスに柔軟性を持たせようとしている恐ろしい方法と関係があることはわかっています。修正できます。 compareTo(Object other)メソッドを削除することでそれを実現しますが、理想的には保持したいと思います。だから私が本当に求めているのは、compareTo(Object other)メソッドを削除せずにこれらのエラーメッセージを非表示にする方法はありますか?これらのエラーは正確にはどういう意味ですか?

また、BigIntegerのような組み込みのJavaクラスなどがすでにいくつかあることを知っていますが、このクラスを使用しようとしているのは、楽しみ/満足のためにやっています。 Project Eulerで使用します( https://projecteuler.net/ )。

Jake@Jake-PC /cygdrive/c/Users/Jake/Documents/Java/Mathematics
$ javac Real.Java
Real.Java:377: error: name clash: compareTo(Real) in Real overrides a method whose erasure is the same as another method, yet neither overrides the other
  public int compareTo(Real other)
             ^
  first method:  compareTo(Object) in Real
  second method: compareTo(T) in Comparable
  where T is a type-variable:
    T extends Object declared in interface Comparable
Real.Java:440: error: name clash: compareTo(Object) in Real and compareTo(T) in Comparable have the same erasure, yet neither overrides the other
  public int compareTo(Object other)
             ^
  where T is a type-variable:
    T extends Object declared in interface Comparable
2 errors

これらはcompareToメソッドです:

  @Override
  public int compareTo(Real other)
  {
    // Logic.
  }
  public int compareTo(char givenValue) 
  { return compareTo(new Real(givenValue)); }
  public int compareTo(char[] givenValue) 
  { return compareTo(new Real(givenValue)); }
  public int compareTo(char[] givenValue, int offset, int count) 
  { return compareTo(new Real(givenValue, offset, count)); }
  public int compareTo(double givenValue) 
  { return compareTo(new Real(givenValue)); }
  public int compareTo(float givenValue) 
  { return compareTo(new Real(givenValue)); }
  public int compareTo(int givenValue) 
  { return compareTo(new Real(givenValue)); }
  public int compareTo(long givenValue) 
  { return compareTo(new Real(givenValue)); }
  public int compareTo(Object other) 
  { return compareTo(new Real(other.toString())); }

必要な場合に備えて、コンストラクター:

  public Real(String givenValue)
  {
    // Logic.
  }
  public Real(char givenValue) 
  { this(String.valueOf(givenValue)); }
  public Real(char[] givenValue) 
  { this(String.valueOf(givenValue)); }
  public Real(char[] givenValue, int offset, int count) 
  { this(String.valueOf(givenValue, offset, count)); }
  public Real(double givenValue) 
  { this(String.valueOf(givenValue)); }
  public Real(float givenValue) 
  { this(String.valueOf(givenValue)); }
  public Real(int givenValue) 
  { this(String.valueOf(givenValue)); }
  public Real(long givenValue) 
  { this(String.valueOf(givenValue)); }
  public Real(Object other) 
  { this(other.toString()); }
14
Jxek

問題のある方法は次のとおりです。

_@Override
public int compareTo(Real other) { ... }

public int compareTo(Object other) { ... }
_

これらのメソッドは同じです erasure つまり、コンパイラがジェネリック型情報を取り除くと、方法はなくなります。実行時にそれらを区別します。

オプションは、compareTo(Object other)オーバーロードを削除するか、Realで_Comparable<Object>_を実装することです。

すべてのcompareToオーバーロードの実装は、新しいRealをインスタンス化してcompareTo(Real)に渡すだけのように見えるので、それらを削除して、変換を呼び出し側:

_Real real = ...;
Object compared = ...;

Real comparedAsReal = new Real(compared);
int result = real.compareTo(comparedAsReal);
_
14
Paul Bellora

RealオブジェクトをObjectと比較できるようにしたいので、implements Comparable<Real>implements Comparable<Object>に置き換えるだけです。これは、Comparable<T>という<T> the type of objects that this object may be compared tojavadocと一致します。

次に、現在のコードを次のように変更する必要があります。

// No more @Override
public int compareToReal(Real other)
{
  // Logic.
}
public int compareTo(char givenValue) 
{ return compareToReal(new Real(givenValue)); }
public int compareTo(char[] givenValue) 
{ return compareToReal(new Real(givenValue)); }
public int compareTo(char[] givenValue, int offset, int count) 
{ return compareToReal(new Real(givenValue, offset, count)); }
public int compareTo(double givenValue) 
{ return compareToReal(new Real(givenValue)); }
public int compareTo(float givenValue) 
{ return compareToReal(new Real(givenValue)); }
public int compareTo(int givenValue) 
{ return compareToReal(new Real(givenValue)); }
public int compareTo(long givenValue) 
{ return compareToReal(new Real(givenValue)); }
@Override
public int compareTo(Object other) 
{ return compareToReal(new Real(other.toString())); }
3

これはJavaジェネリック型消去の副作用です。

ジェネリックインターフェイス、Comparableを実装していますが、これは独自のメソッドであり、ジェネリック型が消去されるとcompareTo(Object)になります。 、したがって、それはあなた自身のcompareTo(Object)と衝突します。

再現するための最小限のコードは次のとおりです。

class Real implements Comparable<Real>
{
    public int compareTo(Object o)
    {
        return 0;
    }

    @Override
    public int compareTo(Real o)
    {
        return 0;
    }       
}
1
Pragmateek