隨筆 - 11  文章 - 33  trackbacks - 0
          <2007年9月>
          2627282930311
          2345678
          9101112131415
          16171819202122
          23242526272829
          30123456

          常用鏈接

          留言簿(1)

          隨筆分類

          隨筆檔案

          文章檔案

          搜索

          •  

          最新隨筆

          最新評論

          閱讀排行榜

          評論排行榜

          本文假定讀者已經(jīng)了解有關(guān)正方形不是長方形的相關(guān)內(nèi)容。
                  
                  之前人們討論的正方形長方形的問題的關(guān)鍵在哪里?我覺得就在于改動長方形的邊的長度。我們可以這么考慮一下,一個長方形的instance的邊長應(yīng)該是可變的嗎?我覺得一旦一個長方形的邊長改變之后它就成了另一個長方形了(一個新的instance)。所以長方形類里面不應(yīng)該有改變其邊長的方法,一個長方形實例各個的邊長應(yīng)當(dāng)在new它的時候確定下來,并且它們應(yīng)當(dāng)是immutable的。基于這種考慮,我設(shè)計的長方形和正方形的類如下所示:
          //長方形
          public class Rectangle {
            private final int width;
            private final int height;
           
            public Rectangle(int width, int height) {
              this.width = width;
              this.height = height;
            }
           
            public int getWidth() {
              return width;
            }

            public int getHeight() {
              return height;
            }
           
            public int getArea() {
              return width*height;
            }
          }

          //正方形
          public class Square extends Rectangle{
            private final int side;
           
            public Square(int side) {
              super(side, side);
              this.side = side;
            }
           
            public int getSide() {
              return side;
            }
          }

                  這種繼承關(guān)系就既符合現(xiàn)實中的父子關(guān)系也遵循LSP。之所以這么設(shè)計,我的想法是一個類所具有的方法不應(yīng)當(dāng)能夠改變其本質(zhì)。比如有一個Men類,它可以有eat(),sleep(),work(),makeLovewith(Person p)方法,但是如果你在里面定義denatureToWomen(),denatureToEunuch()就很不恰當(dāng)了,因為這改變了其本質(zhì),導(dǎo)致這個Men的實例不再屬于Men類(至少已經(jīng)和現(xiàn)實不吻合)了。除非這兩個方法不能改變該實例本質(zhì),否則在Men里面定義這兩個方法本身就是有問題的。不過如果用下面這種方式定義也許可行:
          public Women denatureToWomen() {
            Women w = new Women();
            //set attributes here
            return w;
          }

          public Eunuch denatureToEunuch() {
            Eunuch e = new Eunuch();
            //set attributes here
            return e;
          }

          這樣一來,調(diào)用denatureToWomen()會產(chǎn)生一個新的實例,原來的那個Men實例依然存在,這和現(xiàn)實生活依然不吻合,現(xiàn)實生活中一個實例不光可以上型(upcast),還可以平行型,寒。。。

          總之一句話,一個類的方法不應(yīng)該改變其實例的本質(zhì)。

          posted on 2007-09-20 16:33 teasp 閱讀(2730) 評論(13)  編輯  收藏 所屬分類: Java學(xué)習(xí)

          FeedBack:
          # re: 正方形不是長方形的終極解決辦法 2007-09-20 16:43 千里冰封
          呵呵,有意思  回復(fù)  更多評論
            
          # re: 正方形不是長方形的終極解決辦法 2007-09-20 18:29 GandofYan
          new Square (4,5);

          會有什么結(jié)果呢?  回復(fù)  更多評論
            
          # re: 正方形不是長方形的終極解決辦法 2007-09-20 18:45 teasp
          @GandofYan
          兄弟啊,Square只有一個構(gòu)造方法,你說的這句有語法錯誤哦。  回復(fù)  更多評論
            
          # re: 正方形不是長方形的終極解決辦法 2007-09-20 19:55 GandofYan
          @teasp


          哦,sorry,我一直以為構(gòu)造方法子類是繼承的
          我說錯了:)  回復(fù)  更多評論
            
          # re: 正方形不是長方形的終極解決辦法 2007-09-20 20:38 黑蝙蝠
          makeLovewith你取的方法名字真酷 呵呵

          還是沒明白你到底想表達(dá)什么》??  回復(fù)  更多評論
            
          # re: 正方形不是長方形的終極解決辦法 2007-09-20 21:33 teasp
          @黑蝙蝠

          呵呵,我不知道你有沒有看過關(guān)于正方形不是長方形的討論,網(wǎng)上有的,另外《Java與模式》里面第79頁左右就是講這個問題的。如果你看過相關(guān)的內(nèi)容,應(yīng)該能明白我要表達(dá)的意思了。  回復(fù)  更多評論
            
          # re: 正方形不是長方形的終極解決辦法 2007-09-20 21:49 teasp
          沒看過相關(guān)討論的可以看看這個先:

          長方形有二個屬性長和寬。并有一個設(shè)置長的方法和設(shè)置寬的方法,還有一個求面積的方法.
          像下面
          private int length;
          private int width;
          public void setLength(int lenght) {
          this.length = lenght;
          }
          public void setWidth(int width) {
          this.width= width;
          }
          public int getArea() {
          return this.length * this.width;
          }
          如果說正方形是長方形的子類。為了保證正方形長和寬相等,那對應(yīng)于正方形的二設(shè)置長寬的個方法就得改成
          public void setLength(int lenght) {
          this.length = lenght;
          this.width= lenght;
          }
          public void setWidth(int width) {
          this.length = width;
          this.width= width;
          }
          那我們想想用戶使用時候的情景。 我們都知道長方形的面積等于長與寬的積。那當(dāng)我們用長方形的時候我們會這樣用
          Rectangle rectangle = new Rectangle();
          rectangle.setLength(5);
          rectangle.setWidth(4);
          我們想知道面積是多少我們就可以
          rectangle.getArea();
          得到的是20,當(dāng)然結(jié)果是非常正確的。
          但想想如果我們把一個正方形的實例給用戶用的時候會怎么樣
          Rectangle rectangle = new Square(); //注意,這里體顯代換原則。用戶根本不知道真正的實例是正方形,用戶只知道長方形的事情。
          rectangle.setLength(5);
          rectangle.setWidth(4);
          我們想知道面積是多少我們就可以
          rectangle.getArea();
          得到的結(jié)果卻是 16 ,這違背了長方形的面積是長與寬之積的原則。用戶就不會明白為什么我設(shè)置了長是5寬是4得到的答案卻是16 ?? 與前提不符
          所以正方形不能代替長方形出現(xiàn)在這個地方。
          也就是說正方形不應(yīng)當(dāng)看作是長方形的子類。
            回復(fù)  更多評論
            
          # re: 正方形不是長方形的終極解決辦法 2007-09-21 10:27 辛科
          認(rèn)同樓主  回復(fù)  更多評論
            
          # re: 正方形不是長方形的終極解決辦法 2007-09-21 16:38 dominobaby
          繼承是泛化,是擴展,結(jié)果是:女人不是人,但翠花是人!
          作者的看法確實可取,邊長似乎確實是方形的標(biāo)志性。
          但是這樣的話,哪些作為不可變量很難確定。比如:矮子是不是人?想一個矮子類,就得把高矮也定為不可變量,可是這就跟人的生長特性矛盾了。
            回復(fù)  更多評論
            
          # re: 正方形不是長方形的終極解決辦法 2007-09-21 17:51 teasp
          樓上說得很有道理,最關(guān)鍵的問題是我們不知道哪些特性才是一個類的標(biāo)志。因為現(xiàn)實世界太復(fù)雜了,簡直不可模仿  回復(fù)  更多評論
            
          # re: 正方形不是長方形的終極解決辦法 2007-09-23 20:21 zenny_chen
          我認(rèn)為將正方形作為長方形的子類本身是一個錯誤的概念。
          實際上我們應(yīng)該將面向?qū)ο笾械睦^承與離散數(shù)學(xué)的集合論聯(lián)系起來:
          例如有集合A={a, b, c}, B={a, b}。這里顯然B是A的子集。然而如果用面向?qū)ο蟮姆椒▽⑦@兩個集合構(gòu)造為兩個具有繼承關(guān)系的類結(jié)構(gòu)的話很顯然,應(yīng)該將集合B作為父類而將集合A作為B的子類。
          因此,像public class Square extends Rectangle這種寫法欠妥。作為正方形其元素就只要一個邊長,而矩形則要兩個。因此,根據(jù)上面的集合,可以列出Square={a}, Rectangle={a, b}。很顯然,應(yīng)該將正方形作為父類,而矩形作為正方形的子類。(當(dāng)然,作為集合元素應(yīng)該為集合類型,而不是組合。不過在軟件設(shè)計建模上暫且就如此表示)。

          在做面向?qū)ο蟮脑O(shè)計時,不應(yīng)該死板地去看待現(xiàn)有邏輯,盡管我們一直認(rèn)為正方形是矩形的一個子類(特殊類)。但根據(jù)繼承的概念——子類繼承父類的所有屬性和操作這一概念,在很多時候集合中的子集關(guān)系與面向?qū)ο笾械睦^承關(guān)系是相反的。

            回復(fù)  更多評論
            
          # re: 正方形不是長方形的終極解決辦法 2007-09-23 20:26 zenny_chen
          對了。在這里說明一下,上面提到的“Square={a}, Rectangle={a, b}”中Square和Rectangle是指正方形與矩形的邊長集,而不是指正方形與矩形的集合。
            回復(fù)  更多評論
            
          # re: 正方形不是長方形的終極解決辦法 2007-09-24 10:45 真的遵循LSP?
          長方形在這里只是舉個例子 ,在一個類中改變一個類的屬性的方法是很正常的需求,既然原來的結(jié)論:
          "也就是說正方形不應(yīng)當(dāng)看作是長方形的子類。 "

          那正方形類就不應(yīng)改繼承長方形類.  回復(fù)  更多評論
            
          主站蜘蛛池模板: 乌兰浩特市| 赤峰市| 洪泽县| 大名县| 唐河县| 加查县| 独山县| 固始县| 建德市| 屯留县| 平利县| 宁化县| 唐山市| 阿鲁科尔沁旗| 南城县| 五峰| 建瓯市| 玛多县| 西畴县| 永清县| 清丰县| 双流县| 高台县| 五家渠市| 祁门县| 郧西县| 大竹县| 灵山县| 金堂县| 宁乡县| 乃东县| 云安县| 巫溪县| 平和县| 张家港市| 同江市| 平陆县| 犍为县| 宁安市| 永宁县| 邵武市|