ややこしいのはthisではない
thisはメソッドとフィールドで微妙に違う件 - @katzchang.contextsを見て。Javaのthisがややこしいという話なんですが、ややこしいのはthisではないです。
結論としては、メソッドとフィールドの扱いは違うっぽい。
メソッド(正確にはインスタンスメソッド)とフィールドでちがう、というのはあってるんですけど、thisは関係ありません。メソッドとフィールドで扱いがちがうのはthisに限らないんです。ただの変数でも、評価結果でも、インスタンスメソッドだけが特別扱いです。
実際、
検証
- Hoge#toString()の中で使われるthisは、SubHogeクラスのインスタンス上で実行しても、Hogeクラスインスタンスのnameフィールドを示す。SubHogeクラスインスタンスのnameフィールドではない。
- subHogeをSubHogeクラスとして扱う場合とHogeでキャストした場合とで、subHoge.nameの示す値が自然に変わってたりする。
public class Hoge { public String name = "Hoge"; public void foo() { System.out.println(this.toString()); } @Override public String toString() { return this.name; } public static class SubHoge extends Hoge { public String name = "SubHoge"; } public static void main(String...args) { //当然のケース。 Hoge hoge = new Hoge(); hoge.foo(); //prints "Hoge". System.out.println(hoge.name); //サブクラスのオブジェクトの動作。 SubHoge subHoge = new SubHoge(); subHoge.foo(); //prints "Hoge". System.out.println(subHoge.name); //prints "SubHoge". System.out.println(((Hoge)subHoge).name); //prints "Hoge". } }
と、検証されてるんですが、
System.out.println(subHoge.name); //prints "SubHoge". System.out.println(((Hoge)subHoge).name); //prints "Hoge".
と、thisは全く関係なくフィールドへのアクセスが静的な型で決定される事が確認できます。
subHoge.foo(); //prints "Hoge".
となるのは、fooメソッドはHogeクラスで定義されているためにここでのthisはHoge型の変数(というか暗黙の引数)となるからで、これはフィールドアクセスだろうがメソッドアクセスだろうが一緒です。