QQA: 為什麼java 中要寫getter/setter? - IT閱讀

文章推薦指數: 80 %
投票人數:10人

java 有一個不成文的規定,如果要訪問一個類的private 欄位,就需要寫getter/setter 方法。

但我們在其它語言卻很少見到類似的約定,為什麼? QQA:為什麼java中要寫getter/setter? 首頁 最新 HTML CSS JavaScript jQuery Python3 Python2 Java C C++ Go SQL 首頁 最新 Search QQA:為什麼java中要寫getter/setter? 2018-12-11254 java有一個不成文的規定,如果要訪問一個類的private欄位,就需要寫 getter/setter方法。

但我們在其它語言卻很少見到類似的約定,為什麼? 它是“封裝”的體現,對外隱藏了具體實現,允許之後對屬性的訪問注入新的邏輯(如驗證邏輯)。

一些語言,如python,提供了機制允許我們更改訪問屬性的邏輯,因此不需要手工寫 getter/setter。

#getter/setter是對“屬性訪問”的封裝 假設我們寫了下面這段程式碼,直接訪問類的public欄位: classPerson{publicStringname;}//callerStringname=person.name;person.name="Java"; 之後我們認為name屬性只能是字母,不能包含其它的字元,上面這種實現中,我們就需要更改所有caller呼叫person.name=...的程式碼。

換句話說,類Person暴露了實現的細節(即欄位person)。

那麼如果一開始就使用了getter/setter,則我們不需要改變任何caller,只需要在 setName函式裡增加相應的邏輯即可。

classPerson{privateStringname;publicStringgetName(){returnthis.name;}publicvoidsetName(Stringname){validate_name(name);//thenewlyaddedvalidationlogicthis.name=name;}}//callerStringname=person.getName();person.setName("Java"); 所以,通過這層封裝,之後如果有需要,我們甚至可以更改欄位的名字,型別等等。

這就是封裝的好處,而getter/setter這種寫法能讓我們為將來可能的修改做好準備。

#其它語言裡的getter/setter getter/setter的作用是為“屬性的訪問”(即x.field與x.field=...)提供日後修改的可能。

一些“比較新”的語言就預設提供了這種能力。

Python中提供了Descriptor 的機制。

在Python中,可以認為當訪問物件的屬性時,等價於呼叫物件的__get__() 和__set__()方法,因此我們可以覆蓋這兩個方法來修改訪問的邏輯。

同樣的,Kotlin在定義 properties也可以自定義的getter/setter方法來修改屬性訪問的邏輯。

這裡想說明的是,getter/setter其實應該是預設實現,然後有需要時再覆蓋,而不是每次都手工實現。

#社群與約定 也許你會問,封裝其實叫什麼名字都行,為什麼非要叫getXXX及setXXX呢?這其實是 JavaBeans 里約定的(7.1節)。

甚至從某種角度來說getter/setter的目的也不是為了封裝,而只是一個約定,使框架能識別JavaBeans中的property。

在實際工作中你會發現,90%以上的getter/setter在未來並不會被用來增加邏輯什麼的。

所以“封裝”的作用理論上是好的,但實際被使用到的頻率特別低,反而增加了許多無用的程式碼。

另一方面,隨著使用getter/setter使用的增加,且由於絕大多數getter/setter並不會增加額外的邏輯,使得人們開始習慣於假設getter/setter不會有額外邏輯。

所以如果你想在setter里加一些額外的邏輯時,反而要注意會不會讓使用的人感到吃驚。

#寫在最後 Getter/Setter這個話題看上去似乎很簡單,它的背後卻有很多可以深究和思考的內容的。

有人說Getter沒關係,可怕的是Setter;也有說現在lombok這麼方便,用 Getter/Setter有利無害;也有人說盡量避免使用Getter/Setter。

這些觀點背後都藏著一些軟體的設計思維。

例如怎樣設計類的介面,如何實現封裝,這些都是後續需要學習思考的內容。

相關文章 QQA:為什麼java中要寫getter/setter? 為什麼java中有了基本型別為什麼還要有包裝型別? byte&oxff到底為什麼【java中的負數】 為什麼Java中的String是不可變的? 為什麼java中的時間是從1970年1月1日開始的? 為什麼Java中有三種基礎的類載入器? 為什麼Java中的字串被定義為不可變的 為什麼Java中的float型最大值大於long型? 為什麼C++中宣告和定義要分開寫 java學習筆記--Comparator中為什麼其他類實現這個介面為什麼沒有複寫equals(Objectobj)這個方法? 【Mybatis】為什麼mybatis中,插入引數時,佔位符裡面要寫jdbcType? 為什麼JAVA執行緒中沒有Running狀態? 圖文深入解析JAVA讀寫鎖,為什麼讀鎖套寫鎖會死鎖,反過來卻不會? 【Java關鍵字-Interface】為什麼Interface中的變數只能是publicstaticfinal 為什麼javaHashmap中的載入因子是預設為0.75 分類導航 HTML/CSS HTML教程 HTML5教程 CSS教程 CSS3教程 JavaScript JavaScript教程 jQuery教程 Node.js教程 服務端 Python教程 Python3教程 Linux教程 Docker教程 Ruby教程 Java教程 JSP教程 C教程 C++教程 Perl教程 Go教程 PHP教程 正則表達式 資料庫 SQL教程 MySQL教程 PostgreSQL教程 SQLite教程 MongoDB教程 Redis教程 Memcached教程 行動端 IOS教程 Swift教程 Advertisement 三度辭典 Copyright©2016-2021IT閱讀  Itread01.comAllRightsReserved. 0.001291036605835



請為這篇文章評分?