物件導向之數值的悲劇

2021-05-27 18:34:18 字數 2600 閱讀 3244

上午的時候裡團隊裡開了乙個會,說了一點開發技術問題,在這裡同大家分享一下我的一些想法。

列舉基本用法大家應該都很熟悉,在我們去避免硬編碼,增強**可讀性,可維護性方面很好用。不過話說列舉底層還是比較複雜的,以前看過一些關於列舉的說明。至少c#裡邊的列舉是很複雜的,本身是結構型別(值型別)的,而卻繼承與類system.enum(引用型別),而引用型別system.enum派生與值型別system.valuetype。夠亂吧,其實話說我也沒搞很明白,所以大家千萬不要隨隨便便就說我很了解某個東西之類的話。

好吧,轉入正題(寫東西喜歡扯,沒辦法 ╮(╯▽╰)╭)。

先說一下列舉所帶來的問題。例如,我們有個型別變數,需要儲存到資料庫中。當然儲存到資料庫中的時候,表裡邊存的肯定還是數值(因為列舉終究還是數值)。

例如定義列舉

public enum language

然後假定我們有乙個使用者的名單,這裡邊有個字段記錄這該使用者所使用的語言。那麼資料庫中記錄的就可能是 a 0  b 1  c 3  d 0  e 0  f  1 。ok,現在我們需要新增一種語言,我們在列舉中要加乙個正體中文traditionalchinese,我想很有可能**會變成成這樣子。

public enum language

好吧,悲劇就這樣誕生了。

資料中所有原來已英語為語言的人都改為正體中文了!!是不是很崩潰,而且,這個bug的**錯誤還隱藏的如此之深,是乙個列舉量的順序所導致的。因為traditionalchinese 和 1具有了對應關係。

當然這個問題解決起來不是那麼複雜,目前,如果不變列舉,有兩種方法:

直接在新增新的列舉量的時候,補在japanese後邊,不改變原來的順序

硬性指定各個列舉的值

public enum language

我不會誓死阻止你使用第乙個方法,但是很不建議,因為你無法防範你的朋友不這樣做或者忽略這麼一條怪異的理由。對於第二個方法,比第一方法來說會好一點(可是看著還是有那麼一點不爽),或者,你可以加乙個標註「各個已有的值不可修改」╮(╯▽╰)╭

其他解決方案

既然是由於資料庫中儲存數值所導致的,那麼我們為什麼不直接把列舉.tostring()存進去呢?取出的時候,再做一次強制轉換,這樣不僅解決了上述問題,而且還是在檢視資料庫是可讀性也增強了不少。

換掉列舉

這裡說一下換掉列舉,即列舉的替代

我們可以使用靜態常量來代替列舉。如下

public static  class language

呼叫的時候,也可以向列舉一樣,language.english,可讀性和可維護性都是不錯的。我們還可以定義一些方法,實現列舉類似的功能。我們也可從.net的一些設計上看到這些影子 如webrequestmethods.http.put 等為const string(我還沒有去想用const string 和 static readonly string 的差異,不過實現思想一樣)

。在android中一些設計上也有類似的思想,例如r類的設計。

那麼,在資料庫中儲存的也就是這些變數對應的字串,這個地方和上一種方案是相同的,變數值為字串。

關於列舉就暫時說到這裡。

問題的起因在於,我們要做乙個選單,選單都有索引,比如,最初 索引 0 1 2 3 對應的操單操作是 增,刪,改,查。在**中 我們很肯能會依據索引值來判斷要執行什麼操作(啊,這是多麼危險啊)。後來又多乙個操作為 清空資料。我們想把它放在選單項的第乙個位置,這樣,原有的索引已被打亂,0 1 2 3 所表述的意義已經發生變化了,導致出錯。同樣的,做乙個下拉列表也是同樣的問題。解決方案不複雜,通常這裡邊會提供乙個value,我們在建立item 時,會用這個value來唯一標識該item.這樣,在新增新資料時,他也有自己唯一的value。當然這個value做的時候,也有一些**的技巧。比如我們 先定義一些常量,讓他們的名字分別標識每個item,然後,將這些item的value賦為這些變數。

像是這樣:

private readonly string menuitemadd = "0";

private readonly string menuitemdel = "1";

private readonly string menuitemupdate = "2";

private readonly string menuitemselect = "1";

private readonly string menuitemclear = "1";

menuitem item = new menuitem("增?加", menuitemadd);

menuitem item = new menuitem("增?加", menuitemdel);

當然你可以用乙個類去維護這些readonly string(做這個類的時候,千萬不要就是乙個真正的單獨類,這樣化,你的專案中必將有很多零散的小類,也會使你崩潰,假如你做的是乙個android 應用程式,或許你可以定義activitiesstr類,裡邊在定義乙個 datamangactivitystr類,這個類裡邊再寫datamenuitemvaluestr類,這樣統一維護會好點,至少,我這麼認為。)

ok,這些問題講完了,大家會說這與物件導向有關係麼?還什麼物件導向之數值的悲劇,這不是標題黨麼?

我們來分析一下這些上述問題是怎麼出現的,他們的共性是什麼

物件導向與數值的悲劇

物件導向 之建立物件

為什麼需要建立物件?使用object建構函式或物件字面量雖然可以建立單個物件,但是這樣在需要建立很多物件時,會產生大量重複的 1.工廠模式 優點 可以建立多個類似的物件 缺點 無法識別物件的型別 使用object建構函式或物件字面量雖然可以建立單個物件,但是這樣在需要建立很多物件時,會產生大量重複的...

JS物件導向之物件的屬性

1.屬性的設定和獲取通過 操作符或者 區別 操作符取自身的屬性,可以是變數 var o o.name 緣滅 var aaa name console.log o aaa 緣滅ps 一道比較坑的筆試題 var str abc str 1 var test typeof str if test.leng...

物件導向之介面

1.什麼是介面?還有另外乙個關鍵字,也可以用來定義新的資料型別 inte ce 但是,使用inte ce關鍵字定義的新資料型別,有一些特殊的要求 1.1 在這種資料型別中,只能有方法宣告,不能有方法實現。1.2 在這種資料型別中,所宣告的成員變數,預設都是public static final的。1...