結論、とても手軽だから。
「継承はダメだ」と唱え続けても意味があんまりないなーと思ったので、改めて継承を使いたくなるときを考えてみる話。
基底クラスにそこに別の機能を追加するみたいなシーンという前提。
プログラマの気持ちを想像してみよう。インセンティブから理解していこう。
ちょっと継承して、差分だけ書けば良い。それだけ。やることは少ない。
圧倒的な作業量の少なさ。この誘引力はものすごい。
むしろ、眼の前の問題を解けるソリューションをすぐに見抜けた的な気持ちが、継承の利用を後押しするかもしれない。その瞬間は誇らしくなるのかもしれない。「言語の仕組みにあるわけだろう? じゃあそれを使ってダメなわけないだろう?」
その場の仕事を終わらせたい、終わらせないければいけないというプレッシャーが存在する環境だったら継承を使うインセンティブはものすごく高まる。
ここは本当に馬鹿にできないところだと思う。プログラミング言語というものが未成熟なのが悪いとさえ思う。(「差分プログラミングのためだけに継承するな!」という主張は賛成)
型の意味的な関係をコードで表現を表現したいとき。「シベリアンハスキーはDogだ」みたいな。さすがにそんな実装は稀だと思う。実際は、型の恩恵を受けたいから。コンパイルエラーになるとかね。Lintでもよい。とにかくなるべく早くマズイことを検知したいってこと。
結局、結合しまくる。
1のような差分を継承で攻略する場合、影響範囲はものすごく広がる。つらい。
2も型の階層をどんどん作っていったら、認知負荷が高まってしまう。つらい。
どちらもよくある話だと思う。特に1の差分の話はよくある。飽きた。
それが、インタフェースだとか委譲だとかって話。(あんまりわかってないけど、mixinとtraitもたぶん、そう?)
やりたいことは、各モジュールを交換可能にしたいって話。ポリモフィズムの実現。
継承元にある2つのメソッドだけ欲しいときにどうするか?
継承すれば間違いなくその2つのメソッドは利用できる。
でも、継承元に100個メソッドがあったら、もれなく不要な98個も一緒についてくるね!
ところで、委譲の理解のしづらさは語彙不足もあるかもしれないことに気づいた。
「BinaryExprはNodeだよね」という表現は、is-a(継承)か、has-a(委譲)かは区別できない。
かといって、「BinaryExprはNodeインタフェースを満足しているよね」と言うのは長すぎるので面倒に感じる。面倒だから省略したくなるのは自然。
でも、そうするとコミュニケーションで事故る。
Aさん 「XがYとして振る舞うように実装してね(具象クラスXは、インタフェースYを満たすようにね)」
Bさん 「はい。XがYとして振る舞うように実装すれば良いんですね。(よし、XはYを継承すれば良いんだな)」
語彙は正確に。
ここに、身の回りの日常生活のイメージを持ち込むと逆に混乱する。慣れるまでは比喩表現を使うべきでないと思う。
日本語として「所有する」とか「依頼する」という語彙を使うときは、だいたい人間であることが前提。でも、プログラミングで登場するものはだいたい無生物。
分からない状態においてイメージだけで理解しようとする(させようとする)のはダメだよ。
イメージが分からないなら、イメージが分かるまでプログラミングで示すべきだと思う。
語彙は正確に。
それでも、十分に型の関係性を表現できているっていうか、型の恩恵を受けることができている。ってか、全然困ってない。
以上(いじょう)。
https://twitter.com/mattn_jp/status/1594354661129347078
継承は入門書で学ぶけど、移譲は学ばないからでは?
なるほど。広まってない、勉強していない(機会が少ない)というのは確かに。初学者のみに限定すれば成り立ちそう。
しかし、「入門書に記載があれば、その機能を使いこなせる」はちょっとストレートすぎると思う。初学者でない人も(良くない)継承を使っていたり、使いたくなるシーンはあると思うし、委譲を知っていたとしても意図的に継承を使うケースもありえそうだから。
いくつか分解できそうだ。