JavaとPythonのフィールド初期化タイミングの違い

インナークラスのthisが何をさすかはそのままじゃん。

んー、この感覚の違いが何から生まれるか考えた。

public class TimingOfInitialize {
    public static Foo x = new Foo("outer/static");
    public Foo y = new Foo("outer");
    
    public TimingOfInitialize() {
        System.out.println("init TimingOfInitialize");
        class Bar {
            //error:
            //public static Foo x = new Foo("outer/static");
            public Foo y = new Foo("inner");
        }
        new Bar();
        new Bar();
    }
    public static void main(String[] args) {
        new TimingOfInitialize();
        new TimingOfInitialize();
    }
}

class Foo{
    public Foo(String s){
        System.out.println("initialized!" + s);
    }
}

出力結果

initialized!outer/static
initialized!outer
init TimingOfInitialize
initialized!inner
initialized!inner
initialized!outer
init TimingOfInitialize
initialized!inner
initialized!inner

このようにJavaのstaticでないフィールドの「定義」はクラスの定義時には評価されない。クラスのインスタンスが作成された後で評価されるのでthisにそのクラス自体への参照が入っていてもアリ。

一方Python

>>> class Foo(object):
    def __init__(self, s):
        print s, "initialized"

        
>>> class Bar(object):
    x = Foo()

outer initialized

Pythonではクラスの定義文中に書かれている「Javaのフィールド定義によく似たもの」は即座に評価される。このxはJavaで言うところのstaticなフィールドで、Bar.xとしてアクセスされる。クラスについて話をしているんだからxはクラスオブジェクトに属するものであり、ここでインスタンスへの参照selfとか使えたら変、という考え方。

逆に言えばJavaのstaticでないフィールドの初期化は、Pythonでは__init__メソッドの中に書かれるべきものだから、そこでインスタンスへの参照が使えるのは自然。

というそれぞれの言語の違いに起因している気がした。