河野真治 @ 琉球大学情報工学です。

In article <1173408799.067953.89530@30g2000cwc.googlegroups.com>, "pegacorn" <subscriber.jp@gmail.com> writes
> コンストラクタからインスタンスメソッドを呼び出す場合には下記のような
> 注意が必要ですが、そもそもそんな注意が必要な仕様にしてまで呼び出せる
> ようにする必要があるのでしょうか?

オブジェクトを作成する際には、何らかの初期化が必要な場合が
多いと思います。例えば、MVCだったら、Model と一緒にView も
作らないといけないとか。

> 単純に呼び出せないようにすれば良いのではないでしょうか?

そうすると、
    Hoge hoge = new Hoge();
    hoge.init();
と呼ぶことになると思いますが、繁雑だと感じることもあるでしょうね。

コンストラクタに繁雑なコードを書かれると、それをoverride できなく
なる言語が多いと思います。特に、Default constructor を回避できない。
これは、かなり困る。特に「Contructor の引数が異なると初期化の
状況が異なる」なんてのを食らうと...

なので、僕は、
    class Hoge extends Fuga {
        Hoge() {   init();
        }
みたいな形で書くことが多いです。

> ■コンストラクタからのインスタンスメソッド呼び出しの注意
> ◇C++等の場合
>   メソッドがサブクラスでオーバーライドされていても、サブクラスの
>   メソッドではなく自クラスのメソッドが呼び出される。
> 
> ◇Ruby,Java等の場合
>   メソッドがサブクラスでオーバーライドされている場合、サブクラスの
>   メソッドが呼び出されるが、サブクラスでのコンストラクトが完了して
>   いない可能性がある。

多重継承したクラスの個別の初期化を、どこでどういう順序で
行うかってのは、決った解決策はありません。なので、
    Hoge hoge = new Hoge();
    hoge.init_superA();
    hoge.init_superB();
    hoge.init();
とかいう最低なことをしたくなりますが、この場合は、Factory pattern
を使って、避けるのだと思います。
    class Factory_Hoge {
        Hoge newHoge() {
            Hoge hoge = new Hoge();
            hoge.init_superA();
            hoge.init_superB();
            hoge.init();
            return hoge;

もちろん、

    class Aho extends Hoge {
    void init() {
        super.init();
        自分の初期化;
    }

みたいな形でもいいんですけどね。どうしても、使う方の都合による
初期化が出てくるものなので。

In article <070309124116.M1200468@XP.doga.jp>, Masamichi Takatsu <taka2@doga.jp> writes
> 引数の異なる複数のコンストラクタがある場合に、それぞれのコンストラクタに
> いちいち初期化コードを記述するのは無駄が多いし保守性が悪くなるので、
> 共通の初期化ルーチンはメソッドとして用意して、それぞれのコンストラクタから
> 呼び出す、ということはよくやってます。

それは必須だと思います。コンストラクタは入口に過ぎないので、
実際の初期化は別なメソッドで行うべきでしょうね。

---
Shinji KONO @ Information Engineering, University of the Ryukyus
河野真治 @ 琉球大学工学部情報工学科