次のコードがあるとしましょう
class TestEqual{
public boolean equals(TestEqual other ) {
System.out.println( "In equals from TestEqual" ); return false;
}
public static void main( String [] args ) {
Object t1 = new TestEqual(), t2 = new TestEqual();
TestEqual t3 = new TestEqual();
Object o1 = new Object();
int count = 0;
System.out.println( count++ );// shows 0
t1.equals( t2 ) ;
System.out.println( count++ );// shows 1
t1.equals( t3 );
System.out.println( count++ );// shows 2
t3.equals( o1 );
System.out.println( count++ );// shows 3
t3.equals(t3);
System.out.println( count++ );// shows 4
t3.equals(t2);
}
}
基本的に、TestEqual クラス (もちろん Object を拡張します) には、Object から equals メソッドをオーバーロードするメソッドがあります。
また、いくつかの変数があります。TestEqual としてインスタンス化されたオブジェクト t1、t2、TestEqual としてインスタンス化された TestEqual t3、およびオブジェクトとしてインスタンス化されたオブジェクト o1 です。
プログラムを実行すると、これが出力になります。
0
1
2
3
In equals from TestEqual
4
この例は、通常の Car c = new Vehicle(); よりも少し複雑に見えます。c.drive(); メソッドを呼び出すオブジェクトはその型とは異なるインスタンスであり、メソッドのパラメーターもその型とは異なるインスタンスであるためです。
バインディングに関して、各メソッドを段階的に呼び出したときに何が起こるかを正しく理解しているかどうかを確認したいと思います。
show 0
t1.equals(t2)
show 1
t1 は TestEqual オブジェクトと見なされます。メソッド equals はオーバーロードされているため、バインディングは静的です。これは、t2 をオブジェクトとして渡すことを意味し、オブジェクト スーパークラスから継承された equals メソッドを呼び出すため、テキストは表示されません。
show 1
t1.equals(t3)
show 2
これは少し奇妙に思えます。t3 は TestEqual オブジェクトであるため、「In equals from TestEqual」と表示されることを期待していたので、t1 の equals を呼び出す必要があります。ここでの私の説明は、t1 は静的にバインドされ、オブジェクトと見なされるため、Object クラスから継承されたメソッド equals が呼び出され、パラメーター TestEqual t3 が Object にアップキャストされるということです。しかし、これは t1.equals(t2) からの前の説明が間違っているということではないでしょうか?
show 2
t3.equals(o1);
show 3
t3 は TestEqual オブジェクトで、パラメーター o1 は Object であるため、Object から継承された equals メソッドが呼び出され、何も出力されません。
show 3
t3.equals(t3)
show 4
t3 は TestEqual オブジェクトで、パラメーターは TestEqual オブジェクトであるため、TestEqual からオーバーロードされたメソッドが呼び出され、「In equals from TestEqual」が出力されます。
show 4
t3.equals(t2)
t3 は TestEqual オブジェクトであり、パラメーターは静的バインディング (メソッドのオーバーロード) により Object であるため、Object から継承された equal メソッドが呼び出され、何も出力されません。