継承にかかわる諸問題

「継承」はオブジェクト指向ではよく話題になり、また問題視されます。しかしそれは使い方が間違っているからです。

抽象クラス

抽象クラスというのは、それ自身がインスタンスを作ることはなく、他のオブ ジェクトに継承されるためだけに存在するクラスです。その反対に、インスタ ンスを作るクラスを具象クラスと言います。

と、これが一般の解説 書によくある説明です。この説明は悪い説明ではありませんが、どことなく的 を射ていない感があります [1]。ここでは「抽象クラス」とは何でどう使うべきものなのかを考えてみましょう。

抽象クラスの例

まず、イメージが沸くように例からお話ししましょう。先程「犬」というオブ ジェクトの話をしました。そして同様に「猫」「馬」「豚」といったオブジェ クトも作ったとしましょう。これらのオブジェクトはすべて上位概念である 「動物」というオブジェクトから継承することにしましょう [2]

さて、これらのオブジェクトの例を考えてみましょう。ジョンは「犬」のイン スタンスです。ミーちゃんは「猫」でナリタブライアンは「馬」です。では、 「動物」の直接のインスタンスになるものはあるでしょうか?すべてのインス タンスはこの「動物」のサブクラスのどれかのインスタンスであって、「動物」 の直接のインスタンスになるものはないはずです。これが抽象クラスです。

「タマちゃんのように、犬でも猫でも馬でも豚でもない動物がいたらどうする んだ」と反論する人がいるかもしれませんが、この場合は「アザラシ」という オブジェクトを作ればいいだけの話です。そして逆に、犬とか猫のようにサブ クラスが定義されていない「動物」が出てきたとしたらそれは定義不足なので す。

「犬」や「猫」というのと「動物」というのは観点のレベルが違います。だか ら一緒に扱ってはいけないのです。そして、「観点のレベルが違うオブジェク トが定義されているよ」と示すのが抽象クラスなのです。

抽象クラスは存在しない

「抽象クラスは何か」という説明をしようとしてみましたが、何となく歯切れ が悪い説明に感じたかと思います。その理由は単純。「抽象クラスという概念 は本来は存在しない」からです。抽象クラスという概念はオブジェクト指向プ ログラミング言語のもので、オブジェクト指向のものではないのです。

オブジェクト指向プログラミング言語では、あるインスタンスがどのクラスの ものであるかという情報は重要です。ですから、「ジョン」が「犬」のインス タンスなのか「動物」のインスタンスなのかという区別が必要なのです。しか し、プログラミングを考えなければ区別の必要はありません。「ジョン」は 「犬」であり「動物」である、というだけで十分なのです。「抽象クラス」と いう概念は、プログラムコードを作成する段階まで考えなくてよい概念なので す。

抽象クラスという概念を考えなくてよい理由はもう一つあります。継承される 元(親)のクラスはすべて抽象クラスだからです。だから、「抽象クラス」など という用語を使わなくても、単に「スーパークラス」と言えばすむだけの話な のです。

理由は先程の「犬」「猫」と「動物」の例でおわかりでしょう。スーパークラ スとサブクラスは意味のレベルが違うので、混在させることができないのです。 子供が「ジョンは犬」「ミーちゃんは猫」「タマちゃんは動物」と言ったら、 「おいおい、タマちゃんだけ動物というのはおかしいだろ。タマちゃんはアザ ラシだよ」と注意するでしょう。この通り、混在するのはおかしいことなので す。

具象クラスを継承するな

というわけで、プログラマ向けの一つの注意事項ができました。「具象クラス を継承するな」というわけです。これを守れば、抽象/具象の違いをあれこれ 考える必要はなくなります。

他のライブラリを使う人には一つ特例を設けましょう。他のライブラリに入っ ている具象クラスを「抽象クラスである」と勝手に思い込むのは可能です。あ なたはそのクラスを継承できる代わりに、そのクラスのインスタンスを作るこ とはできなくなります。これで大方の問題は解決できることと思います。

しかし、この規則では、一般の参考書でよく継承の例として挙げられる「一般 のテキストボックスを継承して、数字だけが入れられるテキストボックスを作 る」というような事ができなくなります。一般的に使われるこうした手法を実 現するためにはどうすればいいのでしょうか?

まず「数字だけが入れられるテキストボックスとは何か」ということを考えて みてください。「一般のテキストボックスから数字以外をはじく機能を付加し たもの」という答えはよくありません。これは「機能の継承」ですから。機能 は考えず内包を考えよと言っているではありませんか。

「ここのテキストボックスは個数を入力するためのテキストボックスだから、 数字しか入らないはずであり、そうすべきなんです」という答えはなかなかも のです。そして、名前を入力するテキストボックスには名前しか入らないよう にすべきであり、文章を入力するテキストボックスには文章しか入らないよう にすべきです。あなたはテキストボックスを勝手に抽象クラスだと思い込み、 いろんなテキストボックスのサブクラスを作ることによって、「数字だけが入 れられるテキストボックス」を考えることができます。

抽象クラスの事は考えなくてよい

「内包の継承」の鉄則を守る限り、抽象クラスの事は考えなくていいのです。 単に継承関係があるかないかの問題ですから。そして、あるインスタンスがど のオブジェクトの「直接の」インスタンスかなどという問題も考えなくていい のです。直接のインスタンスであろうと、サブクラスによる間接的なインスタ ンスであろうと、どちらでもたいした違いはないのですから。

そして、これらの問題がもし起きるようなら、そもそもオブジェクトというも ののとらえ方が間違っています。


  1. それはなぜかというと、これが内包による説明ではなく機能による説明だからです。 ↩︎

  2. 「動物」じゃなくて「哺乳類」だろう、と言われる方もあるかもしれません。それはごもっともです。しかし「動物」であってはいけないという理由もありません。「どちらがいいかはドメインによる」というのが答えであって、ドメインを決めていないこの例ではどちらがいいとも言えません。 ↩︎