2019年8月9日 星期五

static 詳解用法及問題

static 詳解用法及問題

從很久很久以前就看到static這傢伙存在於我的程式碼中了

如今我還是不知道他到底是什麼東西,所以我決定來了解他,並且記錄起來

以前對於 static 總是一知半解 只知道哦.....他是一個...........靜態的.......東西?
直到今天看到同事在改工廠方法的作業時提到很多人使用了 static ,於是我就問了為什麼要不加 static 比較好? 他就反問我為什麼要加 static?
在問這個之前我只知道
因為現在在寫測試時,會因為 static 會造成耦合而難以進行 分離單元測試
有時候如果在 class 共用變數時可以用 static
但實際也不了解 static 的存在是為了什麼,到底何時需要用到 static 這個修飾詞

於是乎我就先到了 MSDN 找了他的定義

使用 static 修飾詞來宣告靜態成員,而靜態成員屬於類型本身,而不是特定物件。 static 修飾詞可以與類別、欄位、方法、屬性、運算子、事件和建構函式搭配使用,但不能與索引子、完成項或類別以外的類型搭配使用。 如需詳細資訊,請參閱靜態類別和靜態類別成員

OK,看完了這一段我只知道 static 是一個修飾詞 讓他成為靜態成員或靜態類別成員,媽呀 我還是不知道他到底是什麼鬼東西 於是我看了他後面所提到的文件靜態類別和靜態類別成員

看完了這一個文件我知道了 static 基本上與非靜態類別相同,不同之處的就是他不能使用 new 關鍵字來建立類別類型的變數
不過這對我理解 static 存在到底是為了什麼 還有為什麼不加 static 比較好一點幫助也沒有

於是我又開始找了一些資料 發現了 這一篇文章  ,他舉了許多的例子都蠻有趣的但是易於理解,有興趣可以進去看一看,我在這裡就使用我自己理解的表達方式來用code做紀錄

假設我今天要一個帳戶的class而我的Money使用了靜態類別static,其他的年齡 (Age) 則不加入 static 修飾詞
而我今天寫了一段Code是這個樣子
我用 Account 宣告了兩個人 所以分別有 dz 和 lin ,今天DZ賺了十塊錢
所以理所當然的 dz.Money + 10塊錢 
後來 lin 決定花 10 塊錢買糖果,所以lin.Money - 10
後來 DZ 去查了他的帳戶卻發現他的帳戶剩下了0塊錢!!!
下圖就是執行結果
DZ看到帳戶餘額時整個就是黑人問號
如果像是年齡,我沒有加入 static 修飾詞,則不會共用這一個 Age 的變數,用以下的Code來進行展示
我現在的歲數是18歲嘛 大家都知道(?),而lin的歲數是21歲,今天我過了生日 所以長了1歲,理所當然的 lin的年齡也不會因為我長了一歲而加了1
如果我的Age加了 static 修飾詞 就會變成大家共有這個變數,我長了1歲,lin也會長了1歲,這根本不合理RRRRRRRRRRRRR
所以無論是年齡還是帳戶的錢 都不適合使用 static 這個修飾詞 (除非大家都共用這一個變數

從以上這些程式碼就可以看得出來靜態和非靜態上意義的不同
那何時會需要用到 static 會比較好呢?

簡單以物件導向的方式來解釋用到 static 這個修飾詞時和不使用 static 這個修飾詞時意義上的差異

假設今天有一個公開類別名稱叫做 人類 有個方法叫做賺錢
如果賺錢這個方法是靜態方法 則大家賺的錢就是大家的
如果是非靜態方法  則大家自己賺的錢就是自己的

而為什麼盡量不要使用static呢? 主要會造成的問題是 (引用於 C# Test Legacy Code(4)Unit Test with Static Functions)

  • 無謂地佔住記憶體過久
  • 直接耦合造成無法獨立進行單元測試
  • 無法享用物件導向設計的好處(繼承的重用與擴充、介面的可抽換性、多型的擴充性)
    • 尤其在 Dao 中將 connection 資源宣告成 static 存放更是一件災難,一旦到線上多人一起使用,就會冒出一堆 connection 佔用/使用中的 exception,更可怕的是往往這種 legacy code 還會把 exception 吃掉,假裝天下太平

以上是我對於 static 修飾詞的整理與了解,如果有任何錯誤的地方 麻煩各位大大跟我說 感謝 <(_ _)>

沒有留言:

張貼留言