Swift中自定義下標(biāo)

通常情況下,我們在使用數(shù)組(Array)或字典(Dictionary)時會使用到下標(biāo)脏答。其實在Swift中问慎,我們還可以給類(class)自定義下標(biāo),下面就讓我們來看看Swift中是如何自定義下標(biāo)的倡勇。

通過Subscript賦值和獲取值

我們先看看下面這個類:

class DailyMeal{ 
        enum MealTime 
        { 
              case Breakfast 
              case Lunch 
              case Dinner 
        }  
        var meals: [MealTime : String] = [:]
}

我們使用該類時可以直接用meals字典,以枚舉作為key來查詢嘉涌,像這樣:

var monday = DailyMeal() 
monday.meals[.Breakfast] = "Toast" 
if let someMeal = monday.meals[.Breakfast]{ 
    println(someMeal)
}

到目前呢妻熊,我們創(chuàng)建了DailyMeal類的實例變量monday,并可以使用DailyMeal類中的meals字典進行查詢仑最。但是大家有沒有感覺monday.meals[]這種寫法很累贅呢扔役?至少我看meals就很不順眼,有沒有更簡單快捷的方法讓我們直接使用monday變量就能賦值或獲取Breakfast的值呢警医?別著急亿胸,今天的主角要登場了,讓我們先在DailyMeal類中添加如下代碼:

subscript(requestedMeal : MealTime) -> String?
{
         get { 
                return meals[requestedMeal] 
         } 
         set(newMealName) { 
                meals[requestedMeal] = newMealName 
         }
}

上面的代碼就是一個自定義下標(biāo)预皇,看起來是不是有點像計算類屬性的getter侈玄、setter方法的寫法呢?但是它們還是有區(qū)別的深啤,首先下標(biāo)使用subscript關(guān)鍵字拗馒,然后跟一個圓括號,里面是該下標(biāo)的參數(shù)和參數(shù)類型(在實際使用中該參數(shù)就相當(dāng)于數(shù)組的index和字典的key一樣)溯街,最后有該下標(biāo)的返回值類型诱桂。

從上面代碼可以看到洋丐,在下標(biāo)的gettersetter方法中,其實還是在對meals數(shù)組進行操作挥等,但是我們通過下標(biāo)就可以將對meals數(shù)組的操作屏蔽掉∮丫現(xiàn)在來看看我們應(yīng)該怎樣使用:

var monday = DailyMeal() 
monday[.Breakfast] = "Toast"
if let someMeal = monday[.Breakfast]{ 
      println(someMeal)
     // Toast
}

現(xiàn)在是不是已經(jīng)沒有礙眼的meals了呢,使用起來更加簡潔肝劲,語義也更加明確了呢迁客,這就是下標(biāo)最簡單的一個用法。

如果上面的代碼中我們不給monday[.Breakfast]賦值辞槐,直接輸出值會得到什么結(jié)果呢掷漱?細心的同學(xué)可能會注意到,在定義下標(biāo)時它的返回值是Optional類型的榄檬,所以不賦值直接輸出的結(jié)果是nil卜范,這樣就顯得太沒禮貌了,所以我們再來改造一下下標(biāo)的代碼:

subscript(requestedMeal : MealTime) -> String
{ 
      get { 
            if let thisMeal = meals[requestedMeal] { 
                    return thisMeal 
            } else { 
                    return "Ramen" 
              } 
      } 
      set(newMealName) { 
            meals[requestedMeal] = newMealName 
      }
}

我們看到下標(biāo)的返回值從String?改為了String鹿榜,那么相應(yīng)的我們要在getter方法中對meals[requestedMeal]的值進行判斷海雪,如果沒有賦值的話,我們將返回一個默認值Ramen(蘭州拉面讓人欲罷不能)〔盏睿現(xiàn)在我們就可以這樣用啦:

var monday = DailyMeal() 
monday[.Lunch] = "Pizza"
println(monday[.Lunch]) 
//Output: "Pizza"
println(monday[.Dinner])
//Output: "Ramen"

現(xiàn)在使用DailyMeal類是不是感覺到很簡介奥裸,語義很明確也很健壯呢,答案是肯定的沪袭。我們通過下標(biāo)避免向用戶暴露不必要的API湾宙,同時也達到了高維護性的目的。

DailyMeal類的完整代碼如下:

class DailyMeal{ 
      enum MealTime { 
            case Breakfast
            case Lunch 
            case Dinner 
      }  
      var meals: [MealTime : String] = [:]   
      subscript(requestedMeal : MealTime) -> String { 
      get {
             if let thisMeal = meals[requestedMeal] { 
                        return thisMeal 
                   } else { 
                        return "Ramen"
                        } 
             } 
       set(newMealName) { 
                meals[requestedMeal] = newMealName
               } 
       }
}

只讀下標(biāo)

何為只讀下標(biāo)枝恋,顧名思義就是不能通過下標(biāo)賦值创倔,只能通過下標(biāo)查詢嗡害。這種下標(biāo)的應(yīng)用場景一般是實現(xiàn)一些數(shù)據(jù)公式焚碌、數(shù)據(jù)函數(shù),它們一般都是只需要你指定一個數(shù)字霸妹,然后返回該公式對該數(shù)字的計算結(jié)果十电。下面我們用一個階乘的例子來說明只讀下標(biāo):

struct FactorialGenerator{ 
subscript(n: Int) -> Int {
      var result = 1 
      if n > 0 {
           for value in 1...n { 
                  result *= value 
           } 
      }  
      return result 
    }
}

可能已經(jīng)注意到了,上面的下標(biāo)并沒有gettersetter方法叹螟。這是因為鹃骂,如果你想定義一個只讀的下標(biāo),那么可以不實現(xiàn)setter方法罢绽,并且可以省略getter方法的get關(guān)鍵字畏线。Swfit的編譯器會判斷出這是一個只讀的下標(biāo),如果你強行通過下標(biāo)賦值良价,那么編譯器會報錯寝殴。
讓我們來使用以下這個階乘結(jié)構(gòu)體:

let factorial = FactorialGenerator() 
println("Five factorial is equal to \(factorial[5]).")
//Output: "Five factorial is equal to 120."
println("Ten Factorial is equal to \(factorial[10]).")
//Output: "Ten Factorial is equal to 3628800."

當(dāng)然上面這個示例只是展示了只讀下標(biāo)的語法和應(yīng)用場景蒿叠,階乘的實現(xiàn)邏輯在這就不累贅了◎汲#總的來說市咽,我們可以通過下標(biāo)簡化暴露給用戶的API,你可以在用戶毫不知情的情況下更改某個API的功能抵蚊。不僅使代碼更易讀施绎,同時也大大提高了代碼的可維護性,是不是很酷呢贞绳!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末谷醉,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子冈闭,更是在濱河造成了極大的恐慌孤紧,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拒秘,死亡現(xiàn)場離奇詭異号显,居然都是意外死亡,警方通過查閱死者的電腦和手機躺酒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門押蚤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人羹应,你說我怎么就攤上這事揽碘。” “怎么了园匹?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵雳刺,是天一觀的道長。 經(jīng)常有香客問我裸违,道長掖桦,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任供汛,我火速辦了婚禮枪汪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘怔昨。我一直安慰自己雀久,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布趁舀。 她就那樣靜靜地躺著赖捌,像睡著了一般。 火紅的嫁衣襯著肌膚如雪矮烹。 梳的紋絲不亂的頭發(fā)上越庇,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天奋隶,我揣著相機與錄音,去河邊找鬼悦荒。 笑死唯欣,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的搬味。 我是一名探鬼主播境氢,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼碰纬!你這毒婦竟也來了萍聊?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤悦析,失蹤者是張志新(化名)和其女友劉穎寿桨,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體强戴,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡亭螟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了骑歹。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片预烙。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖道媚,靈堂內(nèi)的尸體忽然破棺而出扁掸,到底是詐尸還是另有隱情,我是刑警寧澤最域,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布谴分,位于F島的核電站,受9級特大地震影響镀脂,放射性物質(zhì)發(fā)生泄漏牺蹄。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一狗热、第九天 我趴在偏房一處隱蔽的房頂上張望钞馁。 院中可真熱鬧,春花似錦匿刮、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至伪节,卻和暖如春光羞,著一層夾襖步出監(jiān)牢的瞬間绩鸣,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工纱兑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留呀闻,地道東北人。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓潜慎,卻偏偏與公主長得像捡多,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子铐炫,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容