Niftyの過去ログ集 - 正方形 is a 長方形?
正方形 is a 長方形?
面白いことに,数学の世界の IS-A 関係は,大抵の場合オブジェクト指向で破綻します.正方形が長方形の一種であるからといって,長方形クラスから正方形クラスを継承するとどうなるか? という話です.
01741/01741 BYI20012 まさーる RE^10:ObjectとClass,メタクラス ( 9) 96/11/22 22:20 01740へのコメント 坂本浩二 さん、こんにちは。 >OOの継承の狙いが、何でもありの状態から絞って行くことだとは言っても、 >インスタンス変数まで、例えば、縦の長さと横の長さの両方を覚えている状態から >縦の長さと横の長さが同じになるよう制限して行く方法でいいのか? >っていうと、違いますからね。 そうですね。単にメモリがもったいないからとかそういうレベルの問題ではなく OOの観点からこの方法はまずいです。普通、長方形クラスのユーザは縦の長さを 変更しても横の長さが変わらないと期待するでしょう。それで長方形オブジェク トをとって縦横の長さを2倍にする関数を、 void func(Rectangle& r) { r.setHeight(r.getHeight() * 2); r.setWidth(r.getWidth() * 2); } のようにしてしまったとしたら、この関数に正方形オブジェクトを渡したときユ ーザの予想に反した結果になってしまいます。(正方形クラスはsetHeightメソ ッドとsetWidthメソッドをオーバーライドして常に縦横の長さがいっしょになる ようにしているとします) >インスタンス変数については、むしろ、何んにも覚えていないという意味で、 >つまり、追加すればどんなふうにもできるという意味で、何でもありの状態と >みなしている、って考えればいいのでしょうか? うーん...どう答えたらいいかよくわからないですが、継承の場合は親クラスの インターフェイスにちゃんと従うのなら最低限子クラスとしての条件を満たして いると思っていいんじゃないでしょうか? 96/11/22(金) まさーる(BYI20012)
上の例は,オブジェクト指向の法則集にある Liskov Substitution Principle(LSP) を破っていることになるわけです.この話は,もともと長方形と正方形ではなく 円と楕円の例として,"The Ellipse-Circle Dilemma" と呼ばれています.
やはりオブジェクト指向の初心者には,LSPをしっかり教えて現実の世界の IS-A 関係とオブジェクト指向の IS-A 関係は違うこともあるんだ,ということを理解してもらわなければならないでしょう.これを知れば,実装継承を控えよう,インターフェイス継承が重要なんだ,ということもわかってきます(ってそこまですぐ行くのは無理かなあ・・).
とはいえ,このことを検証するのは実際難しいと思います.Martin Fowler の本 "Refactoring" (つい先日訳本が出ましたが)で William Opdyke がリファクタリングの安全性のところで指摘してますね.