1

共通のインターフェイスを実装するクラスがあり、オブジェクトがインターフェイスとしてアクセスされるか具体的なクラス インスタンスとしてアクセスされるかに応じて、これらのオブジェクトから異なる方法でハッシュを取得できるようにするドメインの問題に対処してきました。基本的に私が欲しいのは次のとおりです。

public class A implements Bar{
  @Override
  public int hashCode(){ return 1;}

  @Override
  public int Bar.hashCode(){ return 123;}
}
public class B implements Bar{
  @Override
  public int hashCode(){ return 1;}

  @Override
  public int Bar.hashCode(){ return 123;}
}
public class C implements Bar{
  @Override
  public int hashCode(){ return 1;}

  @Override
  public int Bar.hashCode(){ return 123;}
}

Bar interfaceObject = new A();
interfaceObject.hashCode(); //return 123

Bar aObject = new A();
aObject.hashCode();// return 1

私の知る限り、これを行う方法はなく、これが問題を引き起こす可能性がある理由はたくさん考えられますが、私より賢い人に、作成以外でこれを行う良い方法があるかどうか尋ねたかったのです。インターフェースには のような機能がありますpublic int getCustomHashCodeForJustThisInterface()。これらのオブジェクトをフープを介さずに hashMaps で使用できるのは気に入っていますが、hashCode の現在の実装では、これらのオブジェクトは使用方法に応じて ID の複数のビューを持つことができるため、機能しなくなります。 hashCode の基本実装を変更したい。

4

3 に答える 3

4

Java は非ポリモーフィックインスタンスメソッドをサポートしていないため、それはできません (前の回答が示したように、静的メソッドはポリモーフィックではありません)。あなたができることは、あなたのクラスが を直接実装するのではなく、あなたが望むように動作するtype のカスタムオブジェクトを返すまたはメソッドを持つBar別のインターフェース (例えばBarProvider) にすることです。toBar()getBar()Bar

public class A implements BarProvider{
  @Override
  public int hashCode(){ return 1;}

  @Override
  public Bar toBar() {
    return new Bar() {
        @Override
        public int hashCode() { return 123; }
    };
  }
}

A aObject = new A();
interfaceObject.hashCode(); //return 1;
Bar interfaceObject = aObject.toBar();
interfaceObject.hashCode(); // return 123

オブジェクトを final フィールドとして保存する (複数回の初期化を避けるため)、 からにBar戻ることができる逆参照を使用するなど、いくつかの改善が可能です。BarBarProvider


別の可能性は、計算を行う外部プロバイダーを使用することです

public class A implements Bar{
  @Override
  public int hashCode(){ return 1;}
}

public final class BarHasher implements Hasher<Bar> }
  @Override
  public int hashFor(Bar object) { return 123; }
}

A aObject = new A();
interfaceObject.hashCode(); //return 1;
BarHasher.hashFor(aObject); // return 123

または他のメソッドを呼び出す静的メソッド

public class A implements Bar{
  @Override
  public int hashCode(){ return 1;}

  @Override
  public int hashAsBar() { return 123; }
}

public interface BarHasher implements Hasher<Bar> {
  @Override
  public int hashFor(Bar object) { return object.hashAsBar(); }
}

A aObject = new A();
interfaceObject.hashCode(); //return 1;
BarHasher.hashFor(aObject); // return 123

ご存じない場合は、C++ ( virtualJava と同じ動作をするようにメソッドを宣言する必要があります) と C# (ただし、newオーバーライドするメソッドで修飾子を使用しない限り、警告)

于 2013-08-27T19:30:39.267 に答える
2

私が知っているこれを行う方法はありません。


これは、あなたが知らなかったかもしれないことです (私はこれが良い考えだと言っているわけではありません) :

package com.sandbox;

import java.io.IOException;

public class Sandbox {

    public static void main(String[] args) throws IOException {
        A.speak();
        B.speak();

        A a = new A();
        a.speak(); //my ide rightly gives a warning here. static function accessed through instance

        A b = new B();
        b.speak(); //my ide rightly gives a warning here. static function accessed through instance
    }

    public static class A {
        public static void speak() {
            System.out.println("A");
        }
    }

    public static class B extends A {
        public static void speak() {
            System.out.println("B");
        }
    }

}

これは印刷されます:

A
B
A
A

繰り返しますが、これは良い考えではありません。教育目的でお知らせしているだけです。

于 2013-08-27T19:26:39.797 に答える