コンストラクタ

[id:lethevert:20050828:p4]
これは、あれだ。基底クラスと派生クラスの関係だから、この解は適当ではなかったかも。
自分で設計して、こういう構成になっているとすると、たいてい何かの設計ミスだが、自分で設計していないライブラリの機能を拡張したいときとかに、こういう構成をとっていることはないことはない。
スーパークラスがこういう書き方をしていたら、これは逃れるすべはない。

class HogeObject
{
  Base base;
  HogeObject()
  {
    base = new Base();
  }
}
class HogeObjectDeprived : HogeObject
{
  HogeObjectDeprived()
  {
    base = new Deprived();
  }
}

スーパークラスがこういう書き方をしていると、多少救われるが、多少気持ち悪い気もする。この場合、createBase()を何度も使いまわしているような場合だと適当だが、コンストラクタ内だけで使っている場合はよくないように思う。

class HogeObject
{
  Base base;
  HogeObject()
  {
    base = createBase();
  }
  Base virtual createBase()
  {
    return new Base();
  }
}
class HogeObjectDeprived
{
  Base override createBase()
  {
    return new Deprived();
  }
}

継承レベルの違うものを同列に扱うなんて、設計ミスに決まっているといいたいのだけれど、他人が書いたライブラリを使っていると割と起こりうる現象でもある。気持ち悪いけど、我慢して継承するしかない。
ところで、自分で書いていて、総称型が使えるなら、下のような解決がスマートかもしれないと思った。あ、でもjavaだと、この構文はコンパイルエラーか?

class HogeObject
{
  T base;
  HogeObject()
  {
    base = new T();
  }
}