100 Days of SwiftUI —— Day 11:协议和扩展

100 Days of SwiftUI —— Day 11:协议和扩展_第1张图片

今天,您将学习一些真正的Swifty功能:协议和面向协议的编程(protocol-oriented programming —— POP)。

POP消除了大型复杂的继承层次结构,并用可以组合在一起的更小更简单的协议代替了它们。这确实是托尼·霍尔(Tony Hoare)多年前说过话的实现:“在每个大的程序中,都有一个小程序试图跳出来。(inside every large program, there is a small program trying to get out)”

您将使用第一个SwiftUI项目中的协议,它们将在您的整个Swift编码生涯中继续发挥着不可估量的作用——值得花时间来熟悉它们。

今天,您有6个一分钟的视频可供观看,并且您将了解协议扩展以及两者的结合:协议扩展。观看完每个视频后,我们会进行一次简短的测试,以帮助您了解所教的内容。

1. 协议 Protocols – test

协议是描述某些事物必须具有的属性和方法的一种方式。然后,您可以告诉Swift哪些类型使用该协议,该过程称为采用或遵循协议。

例如,我们可以编写一个函数来接受具有id属性的内容,但是我们并不在乎使用哪种类型的数据。我们将首先创建一个Identifiable协议,该协议要求所有遵循协议的类型都具有一个可以读取(“get”)或写入(“set”)的id字符串:

protocol Identifiable {
    var id: String { get set }
}

我们无法创建该协议的实例——它是对所需内容的描述,而不是我们可以直接创建和使用的内容。但是我们可以创建一个遵循它的结构体:

struct User: Identifiable {
    var id: String
}

最后,我们将编写一个displayID()函数,该函数接受任何遵循Identifiable协议的对象,比如上面的User

func displayID(thing: Identifiable) {
    print("My ID is \(thing.id)")
}

2. 协议继承 Protocol inheritance – test

一个协议可以在称为协议继承的过程中从另一个协议继承。与类不同,在顶部添加自己的自定义项之前,您可以同时从多个协议继承

我们将定义三个协议:Payable需要采用的类型来实现calculateWages()方法,NeedsTraining需要采用的类型实现study()方法,然后HasVacation需要采用的类型来实现takeVacation()方法:

protocol Payable {
    func calculateWages() -> Int
}

protocol NeedsTraining {
    func study()
}

protocol HasVacation {
    func takeVacation(days: Int)
}

现在,我们可以创建一个Employee协议,将它们集成到一个协议中。我们可以不需要在上面添加任何内容,因此我们只需要写大括号即可:

protocol Employee: Payable, NeedsTraining, HasVacation { }

现在,我们可以使新类型遵循该单一协议,而不是三个单独协议中的每一个。

3. 扩展 Extensions – test

扩展允许您将方法添加到现有类型中,以使它们执行原本没有设计要执行的操作。

例如,我们可以向Int类型添加一个扩展,以便它具有一个squared()方法,该方法返回当前数字乘以自身的值:

extension Int {
    func squared() -> Int {
        return self * self
    }
}

要尝试该方法,只需创建一个整数,您将看到它现在具有squared()方法:

let number = 8
number.squared()

Swift不允许您在扩展中添加存储属性,因此必须改用计算属性。例如,我们可以向整数添加一个新的isEven计算属性,如果该属性包含偶数则返回true:

extension Int {
    var isEven: Bool {
        return self % 2 == 0
    }
}

4. 协议扩展 Protocol extensions – test

协议可让您描述遵循协议的类或结构体需要有的方法,但不提供内部代码。扩展使您可以在方法内部提供代码,但仅影响一种数据类型——您不能同时将方法添加到许多类型中。

协议扩展同时解决了这两个问题:它们像常规扩展一样,只是扩展了整个协议,以便所有符合条件的类型都可以进行更改,而不是像Int这样扩展特定类型。

例如,这是一个数组和一个包含一些名称的集合:

let pythons = ["Eric", "Graham", "John", "Michael", "Terry", "Terry"]
let beatles = Set(["John", "Paul", "George", "Ringo"])

Swift的数组和集合均符合称为Collection的协议,因此我们可以对该协议编写一个扩展,以添加summary()方法来整齐地打印集合:

extension Collection {
    func summarize() {
        print("There are \(count) of us:")

        for name in self {
            print(name)
        }
    }
}

ArraySet现在都将具有该方法,因此我们可以尝试一下:

pythons.summarize()
beatles.summarize()

5. 面向协议编程 Protocol-oriented programming – test

协议扩展可以为我们自己的协议方法提供默认实现。这使类型很容易符合协议,并允许使用一种称为“面向协议编程(POP)”的技术——围绕协议和协议扩展来编写代码。

首先,这是一个称为Identifiable的协议,该协议要求任何符合条件的类型都具有id属性和identify()方法:

protocol Identifiable {
    var id: String { get set }
    func identify()
}

我们可以使每个采用此协议的类型都编写自己的identify()方法,但是协议扩展允许我们提供默认值:

extension Identifiable {
    func identify() {
        print("My ID is \(id).")
    }
}

现在,当我们创建一个符合Identifiable的类型时,它将自动获得identify()

struct User: Identifiable {
    var id: String
}

let twostraws = User(id: "twostraws")
twostraws.identify()

6. 协议和扩展:总结 Protocols and extensions summary – test

您已经完成了本系列第九部分,所以让我们总结一下:

1、协议描述了采用的类型必须具有的方法和属性,但未提供这些方法的实现。
2、您可以在其他协议的基础之上构建协议,类似于类。
3、扩展使您可以向特定类型(例如Int)添加方法和计算属性。
4、协议扩展使您可以向协议添加方法和计算属性。
5、面向协议编程是一种将应用程序体系结构设计为一系列协议,然后使用协议扩展来提供默认方法实现的实践。

赏我一个赞吧~~~

你可能感兴趣的:(100 Days of SwiftUI —— Day 11:协议和扩展)