Swift進(jìn)階之泛型

swift-generic.jpg

泛型Generic在swift中非常重要,它提升了代碼的通用性和簡潔性,很多開源的組件都是通過泛型來實(shí)現(xiàn)。泛型是什么呢?字面意思大概就是寬泛的類型,在swift中泛型非常靈活,涉及到的概念也相對較多,筆者寫下這篇文章做一個小小的總結(jié),有疏漏的地方以后會慢慢補(bǔ)全。讀者朋友可以在文章底部,找到參考鏈接。

1. 寫一個泛型函數(shù)



func addInts(x: Int, y: Int) -> Int {
    return x + y
}

let intSum = addInts(x: 1, y: 2)
print(intSum)

func addDoubles(x: Double, y: Double) -> Double {
    return x + y
}


func add1<T>(x: T, y: T) {
  return x + y
}

2. 標(biāo)準(zhǔn)庫中的泛型引用

在swift中,標(biāo)準(zhǔn)庫Array, Dictionary, Optional都是基于泛型實(shí)現(xiàn)的,按住鍵盤的option按鍵,鼠標(biāo)點(diǎn)擊下面的數(shù)組和字典變量,即可看到該變量是泛型類型,

let numbers = [1, 2, 3]
let firstNumber = numbers[0]


var numbersAagin: Array<Int> = []
numbersAagin.append(1)
numbersAagin.append(2)
numbersAagin.append(3)
//numbers.append("All hail load")



let countryCodes = ["Arendelle": "AR", "Genovia":"GN", "Freedonia": "FD"]
let countryCode = countryCodes["Freedonia"]


let optionalName = Optional<String>.some("Princess Moana")
if let name = optionalName {
    print(name)
}

3. 泛型類型

通過構(gòu)造一個泛型隊(duì)列Queue,來簡單介紹泛型類型,如下代碼所示,


struct Queue<Element> {
    fileprivate var elements: [Element] = []
    mutating func enqueue(newElement: Element) {
        elements.append(newElement)
    }
    
    mutating func dequeue() -> Element? {
        guard !elements.isEmpty else { return nil }
        return elements.remove(at: 0)
    }
}


var q = Queue<Int>()
q.enqueue(newElement: 4)
q.enqueue(newElement: 2)

print(q.dequeue())
print(q.dequeue())
print(q.dequeue())

在swift中定義class, struct, enum時,都可以通過泛型來進(jìn)行定義,現(xiàn)在定義一個泛型結(jié)構(gòu)體SquareMartrix,它表示一個n * n的矩陣,定義如下,

struct SquareMatrix<T> {
    var backingArray: [T] = []
    let size: Int
    func itemAt(row: Int, column: Int) -> T {
        return ...
    }
    
    init(size: Int, initial: T) {
        self.size = size
        backingArray = Array(repeating: initial, count: size * size)
    }
}

let a = SquareMatrix(size: 10, initial: 50)
let b : SquareMatrix<String?> = SquareMatrix(size: 5, initial: nil)

因?yàn)镾quareMatrix是通過泛型定義,所以可以存放Int和String內(nèi)容。

4. 泛型函數(shù)

下面的泛型函數(shù),將字典內(nèi)容轉(zhuǎn)換為元組數(shù)組,


func pairs<Key, Value>(from dictionary: [Key: Value]) -> [(Key, Value)] {
    return Array(dictionary)
}

let somePairs = pairs(from: ["mininum": 199, "maxinum": 299])
print(somePairs)

let morePairs = pairs(from: [1: "swift", 2: "Generics", 3: "Rule"])
print(morePairs)

5. 泛型約束


func middle<T: Comparable>(array: [T]) -> T? {
    guard !array.isEmpty else { return nil }
    return array.sorted()[(array.count-1) / 2]
}

middle(array: [2, 5, 1, 3, 4])


protocol Summable {
    static func +(lhs: Self, rhs: Self) -> Self
}

extension Int: Summable {
    
}

extension Double: Summable {
    
}


func add2<T: Summable>(x: T, y: T) -> T {
    return x + y
}

let addIntSum = add2(x: 1, y: 2)
print(addIntSum)

let addDoubleSum = add2(x: 10.0, y: 14.0)
print(addDoubleSum)


extension String: Summable {
    
}

let addString = add2(x: "Generics", y: "Are awesome!")
print(addString)

6. 擴(kuò)展泛型類型

在swift中通過extension來進(jìn)行擴(kuò)展,如下代碼所示,為Queue擴(kuò)展一個peek方法,該方法返回隊(duì)列中的第一個元素,


extension Queue {
    func peek() -> Element? {
        return elements.first
    }
}

7. 繼承泛型類型


class Box<T> {
    
}

class Gift<T>: Box<T> {
    func wrap() {
        
    }
}

class Rose {
    
}

class ValentinesBox: Gift<Rose> {
    override func wrap() {
        print("wrap with love paper")
    }
}

class Shoe {
    
}

class GlassSlipper: Shoe {
    
}

class ShoeBox: Box<Shoe> {
    
}

let box = Box<Rose>()
let gift = Gift<Rose>()
let shoeBox = ShoeBox()

let valentines = ValentinesBox()
gift.wrap()

8. 泛型定義枚舉的關(guān)聯(lián)值


enum Result<Value> {
    case success(Value)
    case failure(Error)
}

enum MathError: Error {
    case divisionByZero
}

func divide(_ x: Int, by y: Int) -> Result<Int> {
    guard y != 0 else { return .failure(MathError.divisionByZero) }
    return .success(x / y)
}

9. 在協(xié)議中使用關(guān)聯(lián)類型associatedType作為泛型

在Protocol中不能使用泛型,但可以使用associatedType來替代泛型,如下代碼所示,


protocol Animal {
    associatedtype Food
    func eat(food: Food)
}

struct Cow: Animal {
    typealias Food = String
    func eat(food: Food) {
        print("my food can be any string")
    }
}

let cow = Cow()
cow.eat(food: "corn")

struct Chicken: Animal {
    enum Food: String {
        case grass, corn
    }
    
    func eat(food: Food) {
        switch food {
        case .grass:
            print("My food is a grass enum")
        case .corn:
            print("my food is a corn enum")
        }
    }
}

let chicken = Chicken()
chicken.eat(food: .grass)

struct Dog: Animal {
    typealias Food = [String]
    func eat(food: Food) {
        food.forEach { print("I am eating an array of food, current is \($0)") }
    }
}

let dog = Dog()
dog.eat(food: ["cake", "treat", "bone"])

參考鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,885評論 6 541
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,312評論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,993評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,667評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,410評論 6 411
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,778評論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,775評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,955評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,521評論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,266評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,468評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,998評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,696評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,095評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,385評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,193評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,431評論 2 378

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