>> 正方形は長方形のサブクラスであるとしても成り立つ場合は既に
>> 書きました。is-a と LSP をどうしても両立させられない例を一
>> つでも出していただけませんか。
>
>CES さんご自身が、正方形を長方形のサブクラスに『しない』方が
>いい場合があると、[709]で認めているじゃないですか。常識的に
>は、正方形 is-a 長方形ですから、当然、正方形は長方形のサブク
>ラスとして継承関係を結ぶべきですし、Robert C. Martin 氏のエッ
>セイでも、その方法をまず勧めています。しかし、そうしない方が
>いい場合もあるわけですから、オブジェクト自身の is-a は必ずし
>も判断基準に使えません。
俺はそういうことを言っているのではありません。
LSP なんか関係なく、「正方形 is a 長方形にならない場合もある」ということです。
その場合は、正方形が長方形でないのは何ら問題ではないのですから、「is a と LSP が矛盾する」とは言えません。
「常識的には」と書かれていますが、それが間違いの元です。
世の中に客観的な視点など存在しないというのは以前に書きました。
正方形 is a 長方形というのは、客観的に見えますが、「数学的に都合がいい見方」に過ぎません。常識と言うのも、大多数に都合がいい見方に過ぎません。真理ではないのです。
件の文献の勘違いは「長方形」の定義が曖昧なことです。
「正方形 is a 長方形」は数学に都合がいい見方、「縦と横の長さが独立していなければならない」は、このプログラムに都合がいい見方であって、数学に都合がいい見方ではない。
どちらの見方が間違いというのではありません。どちらも場合によっては正解なのですが、その「場合」が統一されていないのが間違いなのです。
このプログラムが「長方形」に何を期待しているのかが明確になっていないのがいけないのです。
大本の問題は、何のためのプログラムなのかを明確にしないまま、コードだけ示して煙に巻こうとしたことですね。
仮に、「常識的に考えて、正方形 is a 長方形なのだから、当然サブクラスにすべきだ」というのが正しいとして、では「りんご」は何のサブクラスにすべきですか?
常識的に考えて「果物」のサブクラス? それとも「バラ科の植物」? スーパーマーケットのシステム開発だったら「商品」のサブクラスにすべきではないですか?
唯一の正解は無いでしょう。場合によって、適切なものを選べば、それが正解です。
「正方形 is not a 長方形」にすべき場合は確かにあるでしょう。
それは、LSP に都合が悪いからそうなったのではなく、作りたいソフトの目的に合致しないからそうなったのです。
「is-a は LSP と両立できなかったので泣く泣く諦めた」のではなく「そもそも両立する必要が無かった」のです。
現在は is-a が推奨されています。百歩譲って has-a もまぁ認めるとしましょう。
問題は、「LSP さえ成り立つのなら、まったく無関係のクラス同士を継承関係にしていいのか」ということです。
(どういう設計になるのか知りませんが)LSP が成り立つのなら、車を鳥のサブクラスにするのもアリなのですか?
オブジェクト指向の第一目的は「わかりやすくすること」であると(今は)思っています(以前、この掲示板に長期滞在したときは「バグを減らすこと」だと思っていました。考えは変わる可能性があります)。
本来、無関係のオブジェクト同士を継承関係にするのがわかりやすいですか?
>> よろしければ、おすすめの本を紹介していただけないでしょうか。
>
>今回紹介したエッセイ自身を含んだ、Robert C. Martin 氏の
>「アジャイルソフトウェア開発の奥義」はいかがでしょう?
>
http://hamasyou.com/archives/System/aeeoeeueaconoeoeass.php
>
http://hamasyou.com/archives/System/aeeoeeueaoeeoeaass.php
>に長めの紹介があります。
持ってますけど読んでませんでした。
OCP や LSP の評判を聞いて買ったのですが、買ったきりで。
そのうち読むことにしましょう。
こちらにも一点、考え直したことがあったので、最後にそれについて言及します。
オブジェクト指向において、オブジェクトを特徴付けるものは、属性と振る舞いです(プロパティとメソッドとか、メンバ変数とメンバ関数とか、言語によって呼び方はいろいろあるでしょうが)。
つまり、全く同じ属性と振る舞いを持つクラスは、同じクラスだと考えるべきです。
これは、「LSP が成り立つならば is-a も成り立つ」と言い換えることもできます。
しかし、逆に言えば「違うクラスに、全く同じ属性と振る舞いを持たせるべきではない」「関係の無いクラスに、LSP を成り立たせるべきではない」とも言えます。
そう考えれば、「is-a が成り立つのならば LSP が成り立つのは当然」「is-a が成り立たないのならば、LSP も成り立たせるべきではない」のではないでしょうか。