オブジェクトのクラスを途中で拡張可能な言語が欲しい

オブジェクト指向言語の多くでは、サブクラスのコンストラクタからスーパークラスのコンストラクタを呼び出すことは良くある。


しかし、逆がないなぁ、と。


そんなの当たり前?
いやまて、それはプログラミングの常識に対して受身すぎるんじゃないのか?


スーパークラスのコンストラクタ内で、サブクラスのコンストラクタを呼び出したくなることはある……
というか、スーパークラスのコンストラクタ内では、まだ自分自身のオブジェクトがどのクラスに属することになるのか、決めかねるという場合があるわけだ。


構文解析しながらのオブジェクト生成とか、デシリアライズとか、そんな感じの場合ね。


そういう場合に今のプログラミング言語の多くだと、ファクトリーを使ったりするんだよね。
先に構文解析をして、それからどの具体的なクラスを作れば良いかが分かって、それからnewするわけだね。


でもさ……スーパークラスであるabstractクラスのコンストラクタを呼び出すと、先にスーパークラスのメンバを初期化していって、それから作るべきサブクラスが分かって、そこからサブクラスのコンストラクタに入ってオブジェクトを完成させていくって感じのができると、結構便利なことは多いんだよね。


ファクトリーの難点として、段階的に具体的なサブクラスを特定していく場合、途中経過で作成されたデータはサブファクトリーへと全て渡していくのを続けないといけない。
引数が多くなりすぎるのを防ぎたいなら、作成途中のデータを構造体なりでまとめて管理することを思いつくかもしれない。え、でも、それってさ……結局の所、スーパークラスが持つべきデータをサブクラスのファクトリーに渡していくパターンが多いよね。


てわけで、だったら最初から、オブジェクトはクラスの拡張が出来て良いんじゃないかなと思う。
スーパークラスのオブジェクトは、自分を継承しているサブクラスのオブジェクトに、自分自身を拡張可能とするべきだ。
(オブジェクトを外部から参照してる方々にとっても、オブジェクトがいつの間にかより具体的なサブクラスに変わっていても、親クラスとして扱えば良いから、困らない)
スーパークラスのメソッドを呼び出し中に、サブクラスに拡張されてメソッドがオーバーライドされてしまう辺りは、気にかけないといけない気はするけれども)


もちろんこれは、メモリ上のデータ構造を考えると少し難しい。
古くからあるメモリ構造では、サブクラスのオブジェクト内のスーパークラスのフィールドは、サブクラスのフィールドとつながった場所に配置される。その方が高速だからだ。
しかし、この構造だと、スーパークラスが自分自身を拡張しようとした途端に、本来確保していたメモリだと足りなくなってしまい、新しく確保したメモリに全て引っ越す場合は、外部からのオブジェクトへの参照を全て書き換えなければならなくなる。
とりあえずハンドルをかませる様にしておけば、ハンドルの参照値だけ書き換えるだけで良いんだろうけれども、どちらにしても持ってるデータを全て引越ししなければならないのは、しんどい。


なので、オブジェクト内のスーパークラスのフィールドデータは、サブクラスのフィールドデータとは、メモリ上は全然違う場所にあって、サブクラスからはスーパークラスフィールドを参照するようにすれば良い。
これはスーパークラスをメンバとして持つのと、メモリ上は何も違わない気がする。
ただし、外から見たときの継承関係は保たれていて、スーパークラスのメソッドに普通にアクセスできるし、オーバーライドされていればオーバーライドしてるサブクラスのメソッドのほうが呼ばれる。


従来のメモリモデルと比べて、実行速度が遅くなることは間違いないが、こうする方が断然自然な気がする。
遅くなるが、どの程度遅くなるかも微妙で、あんまり遅くならないかもしれない。


なんてことを考えていたのが10年前。
いまだにこういうことができる言語はあまり知らない。
JavaScriptだと、こういう組み方もできるなとは思うけれども、静的型付け言語で、これができる言語というのは、いまだに知らない。
(実際はあるのかもしれない……誰か知ってたら、教えてください)


ちなみに、デシリアライズ中に自分自身のクラスを拡張可能であるというのは、O/Rマッピングする上でも、有利なんじゃないかなと思う。
PofEAAのクラステーブル継承とほとんど同じ形になるから、インピーダンスミスマッチが軽減されるんじゃないかなと思う。
(今の言語の多くは具象テーブル継承に近い形をしてて、でも具象テーブル継承だとスーパークラスとしての検索が不便なので、クラステーブル継承やシングルテーブル継承を使おうとするわけだよね、たぶん)


(できる・できない話だと、今の多くの言語でも「できる」であることは重々承知しています)
(問題は、こういうことを言語側でサポートできれば、今よりすっきり書けることが増えるよ、、、というだけの話です)
(昔、某メーリングリストに投稿してた、switchのdefaultを{}の外に出せる様にしたほうが面白い書き方ができる……ってのと少し似てるのかもしれない)
(経験的には、解読不能文が出てきうる構文解析をコンストラクタ内ですべきではないってのを考えると、微妙な気もしないではないです……)