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__メソッドの中に書かれるべきものだから、そこでインスタンスへの参照が使えるのは自然。
というそれぞれの言語の違いに起因している気がした。