JWorld@TW the best professional Java site in Taiwan
      註冊 | 登入 | 全文檢索 | 排行榜  

» JWorld@TW » Java 新手區 » Object/物件導向  

按列印兼容模式列印這個話題 列印話題    把這個話題寄給朋友 寄給朋友    訂閱主題
reply to topicthreaded modego to previous topicgo to next topic
本主題所含的標籤
作者 其實“封裝”特性到底有什麽好處?對比“private+setter+getter”和“public+直接使用”兩種方法~
timestone





發文: 23
積分: 0
於 2011-10-15 10:55 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
各位好,小弟初學java,現在正在努力體會面向對象編程的精神。但是在參照別人的程序后,自己寫一些當做練習的程序的時候,發現把一個類封裝的很好看起來是很沒有必要的。可能是我還不理解封裝特性的好處,請各位指教。

比如一件簡單的類:
1
2
3
4
5
class A
{
     int number;
     String name;
}


如果安裝封裝的要求,就要限制訪問權限,寫上setter和getter方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class A
{
     private int number;
     private String name;
 
     public void setNumber(int number)
     {
          this.number=number;
     }
     public void setName(String name)
     {
          this.name=name;
     }
 
     public int getNumber()
     {
          return number;
     }
     public String getName()
     {
          return name;
     }
}

這樣用private把屬性封裝起來,最後還是要用public的方法把他們間接暴露出來用,不是很麻煩嗎?再說了,這是基本屬性,最簡單的使用,如果類的屬性里包含一些複雜的,自定義的類型,情況就更是一團糟了。所以我覺得寫setter和getter是一件費力不討好的事。

與其這樣,還不如直接把屬性暴露出來用:
1
2
3
4
5
class A
{
     public int number;
     public String name;
}

可能是水平有限,我實在是看不出他們在應用中的不同,但是在參考別人的程序時,甚至是java的api文檔時,發現大家的java程序都是這麼寫的。。。所以有此一問,請各位不吝賜教~


reply to postreply to post
作者 Re:其實“封裝”特性到底有什麽好處?對比“private+setter+getter”和“public+直接使用”兩種方法~ [Re:timestone]
qwsopp





發文: 3
積分: 0
於 2011-10-15 16:56 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
當你要限定屬性的範圍的時候,不使用封裝就沒辦法阻止使用者輸入例外值
例如你的number只能輸入0~100,你可以透過setter來做判斷
不封裝的話,使用者就可以自由輸入任意數值。


reply to postreply to post
作者 Re:其實“封裝”特性到底有什麽好處?對比“private+setter+getter”和“public+直接使用”兩種方法~ [Re:timestone]
Duncan

還隱隱作痛

版主

發文: 7816
積分: 39
於 2011-10-16 02:12 user profilesend a private message to usersend email to Duncanreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
timestone wrote:
各位好,小弟初學java,現在正在努力體會面向對象編程的精神。但是在參照別人的程序后,自己寫一些當做練習的程序的時候,發現把一個類封裝的很好看起來是很沒有必要的。可能是我還不理解封裝特性的好處,請各位指教。

比如一件簡單的類:
1
2
3
4
5
class A
{
     int number;
     String name;
}


如果安裝封裝的要求,就要限制訪問權限,寫上setter和getter方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class A2
{
     private int number;
     private String name;
 
     public void setNumber(int number)
     {
          this.number=number;
     }
     public void setName(String name)
     {
          this.name=name;
     }
 
     public int getNumber()
     {
          return number;
     }
     public String getName()
     {
          return name;
     }
}

這樣用private把屬性封裝起來,最後還是要用public的方法把他們間接暴露出來用,不是很麻煩嗎?再說了,這是基本屬性,最簡單的使用,如果類的屬性里包含一些複雜的,自定義的類型,情況就更是一團糟了。所以我覺得寫setter和getter是一件費力不討好的事。

與其這樣,還不如直接把屬性暴露出來用:
1
2
3
4
5
class A3
{
     public int number;
     public String name;
}

可能是水平有限,我實在是看不出他們在應用中的不同,但是在參考別人的程序時,甚至是java的api文檔時,發現大家的java程序都是這麼寫的。。。所以有此一問,請各位不吝賜教~


會不會覺得 class A2 的 getter/setter 是多此一舉的做法,與你看這個 class 的方向有關。
若你的看法是 class A2 有兩個不相干的狀態或是欄位:number 與 name,它所提供的就是兩個空間,那麼當然就會覺得 getNumber/setNumber/getName/setName 是多此一舉,不如就不要隱藏這兩個欄位。但如果你是看成每個 A2 object 都有兩個屬性(property)可以讓你去設定其值與取得其值:setNumber/setName/getNumber/getName(重點在於提供這些功能性),而 private int number 與 private String name 二 field 只是實作保存(至少在 object 還活著時)這兩個 property 的方式之一(最簡單地保存在記憶體裡),那麼是不是就不會覺得這樣作很多餘?

物件導向設計時重視的是物件的行為(可使用的操作),對使用物件者來說,怎麼實作出這些操作、怎麼維持它的狀態與外皮之下長甚麼樣子是不重要的(也不應該是重要),重要的是它提供哪些我用的上的操作與如何操作,實作物件時去封裝皮內的血肉結構與運作方式這些細節,可減少使用端對物件的實作細節的依賴(所謂的偶合性),降低實作細節的變更對使用端的影響。

如果你要把 class A 當作純粹是一種數據的容器(不提供任何操作或是說放數據進去與取出不是他要提供的功能),寫成 A3 沒什麼不對,但說起來這樣子就不算是物件導向的做法;如果你是把 A 當作一種可以保存與取回數據的功能性物件,那麼 A2 是多種合理的實作之一。


Duncan edited on 2011-10-16 03:00
reply to postreply to post

給我
辣味豆腐 其餘免談
作者 Re:其實“封裝”特性到底有什麽好處?對比“private+setter+getter”和“public+直接使用”兩種方法~ [Re:timestone]
Ponylin





發文: 38
積分: 0
於 2011-10-16 09:18 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
timestone wrote:
各位好,小弟初學java,現在正在努力體會面向對象編程的精神。但是在參照別人的程序后,自己寫一些當做練習的程序的時候,發現把一個類封裝的很好看起來是很沒有必要的。可能是我還不理解封裝特性的好處,請各位指教。

比如一件簡單的類:
1
2
3
4
5
class A
{
     int number;
     String name;
}


如果安裝封裝的要求,就要限制訪問權限,寫上setter和getter方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class A
{
     private int number;
     private String name;
 
     public void setNumber(int number)
     {
          this.number=number;
     }
     public void setName(String name)
     {
          this.name=name;
     }
 
     public int getNumber()
     {
          return number;
     }
     public String getName()
     {
          return name;
     }
}

這樣用private把屬性封裝起來,最後還是要用public的方法把他們間接暴露出來用,不是很麻煩嗎?再說了,這是基本屬性,最簡單的使用,如果類的屬性里包含一些複雜的,自定義的類型,情況就更是一團糟了。所以我覺得寫setter和getter是一件費力不討好的事。

與其這樣,還不如直接把屬性暴露出來用:
1
2
3
4
5
class A
{
     public int number;
     public String name;
}

可能是水平有限,我實在是看不出他們在應用中的不同,但是在參考別人的程序時,甚至是java的api文檔時,發現大家的java程序都是這麼寫的。。。所以有此一問,請各位不吝賜教~


其實封裝物件的私有屬性,這只是學Encapsulation的第一步而已,OO重視「抽象化」與「資訊隱藏」,藉由適當的封裝,可以達到一些資訊隱藏的效果... 藉由封裝,隱藏了內部實作的細節,並對外提供一致的公開的API! 某種程度上,「一致的」蠻重要的...

以後慢慢接觸到design pattern之後,封裝只是一種概念,可不只是把屬性宣告為private,用getter、setter這樣而以,封裝請求、封裝實作、封裝一群相似/相近的演算法、封裝一群子系統,很多概念都是封裝出來的...

這種封裝的概念,實際上也不是只有Java才有,只要OO的語言幾乎都有,像C#、C++甚至更先進一點的Python...
可以參考一下這篇文章
http://caterpillar.onlyfun.net/Gossip/JavaEssence/Encapsulation.html


reply to postreply to post
喜歡自由/前衛爵士樂的Java新手
作者 Re:其實“封裝”特性到底有什麽好處?對比“private+setter+getter”和“public+直接使用”兩種方法~ [Re:timestone]
timestone





發文: 23
積分: 0
於 2011-10-16 10:01 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
的確我現在看到的類,只是看到了一個實在存在的屬性的容器,而沒有考慮這個類的功能性。這樣看來,實現一個自定義數據類型的類,不只是給他設置好指定的屬性和類型就OK了,還要考慮到在實際使用這個類的對象時的特定限制要求、使用的方便性甚至是與其他類或者API的一致性。。。

以上種種,一個一個的函數一定可以做的比一個乾巴巴的public屬性做的更多更好,所以雖然麻煩了點,這就當做我學習封裝的第一步吧~

最後,非常感謝各位的解答!這些東西實在是我看書所看不來的,希望以後有機會咱們繼續交流~


reply to postreply to post
作者 Re:其實“封裝”特性到底有什麽好處?對比“private+setter+getter”和“public+直接使用”兩種方法~ [Re:timestone]
ddtet





發文: 114
積分: 0
於 2011-10-17 09:24 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
個人是覺得,原 po 的例子是「以技術來看說明簡單」但是「以概念而言說明困難」。

我另外舉一個例子,假設你今天寫一個偵測溫度和濕度的類別,其它類別可以得到你所偵測到的資料,
因此其它的類別可以依靠資訊決定是否要啟動室內空調,或是啟動澆花的灑水系統。

(先說明一個前提,「其它的類別」可能是由任何一個人寫出來的)

如果說今天你將屬性(特性)設定成 public 的話,你可能會擔心哪一個天才,去修改你所偵測到的資料,
造成別的類別判斷錯誤,造成你不希望發生的現象,那麼你將會希望你所偵測到的屬性(特性)是唯讀(只讀)的。

因此你可以決定只撰寫 getter 函數,而不撰寫 setter 函數,來確保所有人取得的資料,都是由你所控管的。
換言之,這就是「封裝」這個概念想要提供的「保護」機制。

我認為,物件導向的發展是為了應付大型/複雜的程式,以及多人協作/組合出專案功能所効產生。決對不是記熟定義或理論內容就能夠活用,得靠實作中的經驗的累積才能了解原因。

個人建議,先記得有這麼一個概念就好,等到專案變大或是工作人數變多的時候,再去思考這個問題。

記得我當年自學程式,用了一年才知道 class 是啥東東,學到物件導向概念之後,也是隔了一年才慢慢了解它的精神所在。
到目前為止,我還在不斷的學習物件導向的精神當中…


reply to postreply to post
技術很重要... 所以要增加技術力...

但是技術到一個階段... 想法就很重要了...

技術不夠是作不出來...
想法不對是作到死....
作者 Re:其實“封裝”特性到底有什麽好處?對比“private+setter+getter”和“public+直接使用”兩種方法~ [Re:timestone]
jimwayne





發文: 220
積分: 0
於 2011-10-17 11:45 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
小弟個人是想推 ddtet 大的回應
很多觀念都是真的做到比較大的專案以後才會發現這麼做的意義在哪裡~

另外提供一個前幾天在書上看到的內容
它說使用封裝通常會造成效能上的一點點損失,但可以帶來維護上的方便性
例如今天我有一個取得某個值的 method,原本使用 array 來實作
但如果改成 linked-list 也許效能比較好?
如果沒有將整段程式碼封裝成一個 getter,那可能改這一樣東西要在專案裡面翻來翻去
找各處有寫到這個功能的 code,並且把它改成 linked-list
不過如果一開始就用 getter 封裝好了,我只要在 getter 裡面把原本的程式碼註解掉
改成新的 code,整個專案所有用到這個 getter 的地方馬上就跟著更新了
這樣可以省去很多無謂的時間在搜尋和修改程式碼。


reply to postreply to post
Java 工作者,但仍然是個初心者.....
作者 Re:其實“封裝”特性到底有什麽好處?對比“private+setter+getter”和“public+直接使用”兩種方法~ [Re:timestone]
caterpillar

良葛格

版主

發文: 2613
積分: 70
於 2011-10-17 11:50 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
單純用公開(public) Getter/Setter 來作為封裝的例子並不是很好,通常這類範例實作 Getter/Setter 單純只對內部 private 取值或設值,沒有流程控管的實現,雖不是沒有其應用場合,例如 JSP 使用 JavaBean 時,多數通常就是這類的 Getter/Setter,不過對初學物件導向的人來說,不易體會或難以信服封裝的好處。

早期我寫作文件時,也是沒注意到這點,而單純使用 Getter/Setter 來說明 public、private 等語法,但沒有真正說明封裝實際作用,除了上面網友貼的連結網頁,有作較多封裝實際作用說明之外,建議還可以參考這邊開放的文件:
https://plus.google.com/100835675055840789478/posts/DV2m3sgcAaZ


reply to postreply to post
良葛格學習筆記
作者 Re:其實“封裝”特性到底有什麽好處?對比“private+setter+getter”和“public+直接使用”兩種方法~ [Re:timestone]
timestone





發文: 23
積分: 0
於 2011-10-17 21:30 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
犧牲效率所換來的維護性上的方面,的確是自己在做一些小的、實驗性的專案的時候難以理解的,但是我也體會過面對自己寫的一個2000+行代碼的五子棋程序,卻無從下手去添加一個小功能的尷尬。

偶爾我會懷念當年大一初學C語言時候那種用乾巴巴的代碼去追求所謂“簡潔”的時候,但是java的確教會了我更多東西,異常處理、封裝...現在開始接觸web開發了,更加的感覺很不適應,希望我能在以後做的更好吧~

PS:好多連接點不了。。。現在想翻牆查資料也不容易了的說~


reply to postreply to post
» JWorld@TW »  Java 新手區 » Object/物件導向

reply to topicthreaded modego to previous topicgo to next topic
  已讀文章
  新的文章
  被刪除的文章
Jump to the top of page

JWorld@TW 本站商標資訊

Powered by Powerful JuteForum® Version Jute 1.5.8