[722] Re:オブジェクト指向「初」入門
投稿者:CES
2007/02/20 02:13:25
>「is-a の意味は常識的なものとは限らない。場合によって、適切なもの
>を選べ」というのは、実のところ、まったく意味のない言明です。なぜな
>ら、CES さんは、is-a という関係が具体的にどうあるべきかを一切述べ
>ていないからです。
どう言えばいいですかねぇ。
「クラスはオブジェクトの集合である」と考えた時、「ある集合Aと、その部分集合Bがあったら、B is-a Aである」でいいですか?
もっとも、「どのような基準に従ってオブジェクトを集合に分類するか」には、結局、唯一解がないのは同じことなんですが。
>我々は、設計段階で、どういう継承関係にすればうまくいくかを知りたい
>ため、設計原則を求めているわけです。
そんな話は今初めて聞きましたがねぇ…
>たとえば、「常識的に考えた is-a 関係に対して、継承を当てはめれば良
>い」というのは、正方形と長方形の例のようにうまくいかない例外もあり
>ますが、かなり使える原則です。
それでいいと思いますよ。
我々の社会常識が「大多数にとって都合がいい見方」であるように「多くの場合に都合がいいケース」はあってもおかしくありません。
ただし、それがたまたま成り立たないからといって、それだけを槍玉に挙げないでいただきたい。
ちなみに、件の文献の、長方形と正方形の関係の誤りは、LSP を持ち出すまでも無く「間違いだ」と判断できるものです(まぁ、LSP を考えてみて判断しても構わないのですが。別にそれでも is-a と LSP の矛盾は指摘できませんから)。
オブジェクトの is-a よりも LSP を優先すべきだという根拠にはなりません。
>また、「LSPに従うオブジェクト同士に対して、継承を当てはめれば良い」
>というのは、常に利用可能な原則です。
>ところが、CES さんは、「継承してうまく動くような関係が is-a である。
>したがって、継承してうまく動くような関係に対して、継承を当てはめれ
>ば良い」と言ってるに過ぎないわけです。これは見て分かるようにトート
>ロジーに過ぎず、設計の指針としては、全く役に立たないわけです。
違います。
「どういう関係が is-a であるか」については言及していません。
「is-a である関係が、LSP を満たすように作れ」と言っているのです。
件の文献も言っているではありませんか。
> あるところで、何か、置き換えが必要なところがあるとする。
> 型Sのオブジェクトo1 と、型Tのオブジェクトo2があって、
> プログラムが既に型Tのオブジェクトを使うように構築されているとする。
> o1がo2で置き換えられても、SがTのサブタイプであるならば、
> Pは同じ振る舞いをするべきである。
「サブタイプならば同じ振る舞いをすべきである」と書かれています。
「同じ振る舞いをするならサブタイプである」とは書かれていません。
結局、この文献は「どんなものを継承関係にすべきか」という指針には、一言も言及していないのです(「どんなものを継承関係にしてはいけないか」は、LSP を用いて言及しています。しかし、それは LSP を用いなくても指摘可能であることは度々述べています)。
>> 全く同じ属性と振る舞いを持つクラスは、同じクラスだと考えるべきです。
>> これは、「LSP が成り立つならば is-a も成り立つ」と言い換えることもできます。
>
>一つ目の文章は正しいと思います。
>しかし、一つ目の文章から二つ目の文章を導くことはできません。
突っ込まれるかなーと思っていました。
ちょっと拡大しましょう。
全く同じ属性と振る舞いを持つクラスは、同じクラスだと考えるべきです。
そして、あるクラスと互換性のある属性と振る舞いを持つクラスは、そのクラスと何らかの関係があるクラスと見るべきです。
逆転させて言えば「関係の無いクラスに、互換性のある属性と振る舞いを持たせるべきではありません=継承関係にすべきではありません=LSP が成立してはいけません」となるのではないでしょうか。
>なお、Martin 氏の文章を読み返してみて、私がこれまで説明で使って
>用語法が、Martin 氏の用語法と異なっているのに気づきました。
>私がこれまで
>1. オブジェクトの振舞いに関する is-a
>2. オブジェクト自身に関する is-a
>という二つの言葉で区別してきたことを、Martin 氏は
>1. 振舞いの is-a == オブジェクト(CamelCase にした名詞)の is-a
>2. 物(子文字で始まる名詞)の is-a
>と呼んでいますね。
>まあ、独立に読んでいれば意味は通じると思いますが、併せて読むと
>混乱するのであまり良くありませんね。どうも申し訳ない。
小文字の is-a ってどこで使ってますか? ひょっとして原文?
提示された日本語版には見当たらないのですが…
>設計手順としては、まず常識的な is-a を使って継承関係を考えてみた
>上で、それを LSP で検証すればいいんですよ。検証に通らない場合には、
>たとえ常識的なis-a 関係であっても、継承関係にはしません。検証に通
>れば、もちろん継承関係にします。
>簡単でしょう?
>本来無関係のオブジェクト同士うんぬんなどと悩む必要はありません。
議論が空転している気がするんです。整理しましょう。
まず(常識的かどうかは置いておくとして)「オブジェクトの is-a」で大まかな関係を作るというのは、どちらも同じことを言ってますね。
kit さんは、その上で「LSP に照らして破綻したら、継承関係にはしない」と言う。
俺は「LSP に照らすまでも無く、継承関係にしてはいけない場合がある」と言う。
結局、どの段階で、最初の「is-a」が間違えていたかを判断するのかが違うだけで、大差ないでしょう。
問題は「LSP に照らさないと、間違いかどうか判断できないケースはあるのか」だと思うんですよ。
そのへんどうです?
>なお、もし本来無関係だと思っていたオブジェクト同士にLSPが成り立つ
>のであれば、実はそのオブジェクト同士は、たぶん無関係じゃないんですよ。
本当に無関係でないのなら構いませんが、「たぶん」というのはいただけません。
実のところ、「本当に無関係か」を判断することはできません。どうにかして関係を見出すことはできます。
しかし、その関係は、設計者の意図した関係で無い可能性が大きいでしょう。
そのような関係に、LSP を成り立たせることは、メリットがあるとは思えません。
>しかし、通常のソフトウェア開発で、そういう発見を必要とすることは
>あまりありませんから、無関係だと思うオブジェクト同士について、
>いちいちLSPを検証してみる必要はありません。
LSP は「たまたま成り立っちゃう」ものではなくて「意図して成り立たせる」ものであると考えます。
であるならば、先のようなデメリットを考えた時に「意図して崩す」ことも、当然ありえる話です。
それをせず、「たまたま成り立っちゃう」のを放置しておくのは、バグの温床になりませんか。