专栏首页韦弦的偶尔分享100 Days of SwiftUI —— Day 11:协议和扩展

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

今天,您将学习一些真正的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. 协议 Protocolstest

协议是描述某些事物必须具有的属性和方法的一种方式。然后,您可以告诉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 inheritancetest

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

我们将定义三个协议: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. 扩展 Extensionstest

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

例如,我们可以向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 extensionstest

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

协议扩展同时解决了这两个问题:它们像常规扩展一样,只是扩展了整个协议,以便所有符合条件的类型都可以进行更改,而不是像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 programmingtest

协议扩展可以为我们自己的协议方法提供默认实现。这使类型很容易符合协议,并允许使用一种称为“面向协议编程(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 summarytest

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

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 微信小程序后台返回大量多余数据的处理

    其实我只要id和name,找后台解决、、、算了吧,奈何天生就是个儒生,温文尔雅,打架是打不赢的,要是能打赢的就直接打吧,打完让他们改!

    韦弦zhy
  • SwiftUI:渐变色

    SwiftUI为我们提供了三种可以使用的渐变,就像颜色一样,它们也是可以在我们的UI中绘制的视图。

    韦弦zhy
  • Swift:轻量级API的设计(一)

    Swift的最强大功能之一就是在设计API方面给我们提供了极大的灵活性。这种灵活性不仅使我们能够定义易于理解和使用的函数和类型,还使我们能够创建给人以非常轻量级...

    韦弦zhy
  • GCAC97 21.7 Deniability & 21.8 Channel bindings

    21.7.2 Deniability with identity protection

    安包
  • 速读原著-TCP/IP协议(概述)

    很多不同的厂家生产各种型号的计算机,它们运行完全不同的操作系统,但 T C P / I P协议族允许它们互相进行通信。这一点很让人感到吃惊,因为它的作用已远远超...

    cwl_java
  • [译]聊聊C#中的泛型的使用(新手勿入)

    今天忙里偷闲在浏览外文的时候看到一篇讲C#中泛型的使用的文章,因此加上本人的理解以及四级没过的英语水平斗胆给大伙进行了翻译,当然在翻译的过程中发现了一些问题,因...

    依乐祝
  • 程序的编译、链接、装载与运行

    在Linux操作系统中,一段C程序从被写下到最终被CPU执行,要经过一段漫长而又复杂的过程。下图展示了这个过程

    shengjk1
  • 1634: [Usaco2007 Jan]Protecting the Flowers 护花

    1634: [Usaco2007 Jan]Protecting the Flowers 护花 Time Limit: 5 Sec  Memory Limit:...

    HansBug
  • 2017年全球金融科技100强发布!中国9家金融科技企业上榜!

    近日,毕马威和H2 Ventures联合发布了“2017年全球金融科技100强报告”,报告从全球范围内选出了最具创新性的100家金融科技企业,这100家金融科...

    点滴科技资讯
  • DAY6:阅读 CUDA C编程接口之CUDA C runtime

    GPUS Lady

扫码关注云+社区

领取腾讯云代金券