イノベーション エンジニアブログ


株式会社イノベーションのエンジニアたちの技術系ブログです。ITトレンド・List Finderの開発をベースに、業務外での技術研究などもブログとして発信していってます!


このエントリーをはてなブックマークに追加

「多重継承」と「クラス分割」と「オブジェクト指向プログラミング」について勉強したメモ

みなさんこんばんは。bigenです。

先月、プログラマになって1年経ちましたが、
恥ずかしながら先日はじめてPHPのTraitという機能を知りまして、
そこから色々勉強したので、とりとめもなくメモしていきます。

目次

  1. Traitってどう使うの?

  2. 多重継承のデメリット

  3. 水平継承しないほうがよさそうなケースについて

  4. オブジェクト指向プログラミング(OOP)的な観点では

  5. おわりに

1. Traitってどう使うの?

PHPにはTraitという水平継承の機能があるそうです。
機能の詳細や使い所は下記を参照してください。

ぱっと読んだら実に便利そうなんですが、いくつか疑問点が。

①始めから複数クラスを継承できるようにすればいいのでは?
②Utilityクラスを水平継承するというやり方は良いやり方なのだろうか?
③そもそも継承っていう機能ってなんのためにあんの?

これらについて考えました。

2. 多重継承のデメリット

①始めから複数クラスを継承できるようにすればいいのでは?

Traitは水平継承と書かれていますが、結局のところ複数のクラスを継承できることを意味します。
つまり、水平継承ではなく多重継承。
PHPは単一継承しか許さないという縛りがある一方で、同時に多重継承させるような機能を提供するのは謎です。
はじめから多重継承できるようにしとけよって思いました。

というわけでなぜ単一継承なのか調べました。

参考3: 【雑記】 多重継承できない理由

このサイトでは 実装上のコスト の問題が触れられています。なるほど・・・。
こういった多重継承にまつわる問題に対処するため、Mixinという機能もあるそうです。
Trait機能に関しても、単純な継承にはないいくつかのルールや制約があるのもそれが理由でしょう。

社内で話を聞くと、設計時のリスクについての話題も出てきました。
つまり、用心深くクラス設計を行わないといわゆる キメラクラスが作られてしまう ということです。
これは多重継承だからこそ起きる問題ではないのですが、単一継承のほうが設計が容易でキメラをつくりにくいため安心のようです。

他にも、安直な実装をするとクラス間の暗黙の依存関係が生まれやすく、メンテナンス性を損ないやすいなどの問題も指摘されています。

そんなこんなで、ただ闇雲に多重継承を使ってしまうと結局デメリットのほうが大きくなってしまうため、 実装者のスキルがかなり高くないと使わないほうが良い という意見が多いようです。
また、それゆえに多重継承を言語としてそもそも禁止してしまっているものも多く、PHPもその一つのようです。

3. 水平継承しないほうがよさそうなケースについて

②UtilityクラスをTraitにして水平継承するというやり方は良いやり方なのだろうか?

ぱっと思いつく水平継承(多重継承)の使い方は、
色々なクラスで共通で使うUtilityメソッドをもったクラス(Utilityクラスと呼ぶ)を継承することでした。

でもUtilityクラスと呼び出し元クラスと依存性が少ないのであれば、メソッドを静的呼び出ししたり、必要であればインスタンス化して使えばいい気がするんですよね。
(ここでは計算量的コストはいったん無視してます)

「継承」しなければいけないということは、ポリモーフィズムを期待するということです。
しかし、Utilityメソッドのポリモーフィズムは、Utilityクラスでやっとけばよくない?まるごと継承する意味ある?ということです。

では水平継承すべきものとは・・・?
今回はそこまでよくわからなかったので自分の宿題にしておきます。

4. オブジェクト指向プログラミング(OOP)的な観点では

③そもそも継承っていう機能ってなんのためにあんの?

そもそもクラスとか継承とかなんでやってんの?ポリモーフィズムも結局メソッドをif分岐すればいいだけだし?
というわけで、これを機にOOPについても勉強してみました。

余談ですが、色々調べて見えてきたのは、「オブジェクト指向プログラミングは世の中のモノ(オブジェクト)を全て表現できる」という説明が とんでもない罠 で、理解を阻んでいることでした。
OOPは世の中のモノを表現するための概念である、というミスリーディングを生じさせる表現です。
また、このミスリーディングは先の発言者本人も認めています。

参考4: 新人プログラマに知っておいてもらいたい人類がオブジェクト指向を手に入れるまでの軌跡

プログラム管理の歴史的流れを見れば、OOPは構造化プログラミングに端を発する 処理の構造化・データの構造化における洗練された一形態 でしかないようです。
また、OOPの概念の中ではポリモーフィズムは必ずしも「継承」という実装を必要としないことも分かります。
(とはいえ「継承」システムはポリモーフィズムの本質を表現していて、ほぼすべてのOOLが利用している)

この辺りの観点から見ていくと、「どう上手く"継承"するか」ではなく、
まず「どのようにオブジェクトが分割されているか」が前提にあって、
その上で互いにどのようにメッセージングするかを考えるべきなのでしょう。

5.おわりに

オブジェクト指向についてゆっくり学べたところで、満足して今回はここまでにしておこうと思います。
上手な水平継承の一般化については、今後の開発の中で考えていこうと思います。

ところで、「継承」以外の概念でポリモーフィズムを実装しているオブジェクト指向言語があれば是非教えてください。

それでは。