Swift 面向协议编程入门

简介: 本文讲的是Swift 面向协议编程入门,这个教程也是为了那些不知道类和结构体根本区别的人写的。我们都知道在结构体里是没有继承的,但是为什么没有呢?
本文讲的是Swift 面向协议编程入门,

面向对象编程的思想没毛病,但老铁你可以更 666 的

上图这个人不是我,但这就是使用面向协议编程替换掉面向对象编程之后的感觉。

介绍

这个教程也是为了那些不知道类和结构体根本区别的人写的。我们都知道在结构体里是没有继承的,但是为什么没有呢?

如果你不知道上面问题的答案,那么花几秒钟看下下面的代码。请再次原谅我的排版,我已经让它尽可能的简单明了了。

注:译者已经改过排版了 :thinking:

class HumanClass {
    var name: String
    init(name: String) {
        self.name = name
     } 
}

var classyHuman = HumanClass(name: "Bob")
classyHuman.name // "Bob"

var newClassyHuman = classyHuman // Created a "copied" object

newClassyHuman.name = "Bobby"
classyHuman.name // "Bobby"

当我把 newClassyHuman 的 name 属性设为 “Bobby” 之后,原来对象 classyHuman 的 name 属性也会变成 “Bobby” 。

现在,让我们来看一下结构体的情况。

struct HumanStruct {
	var name: String 
}
 
var humanStruct = HumanStruct(name: "Bob" )
var newHumanStruct = humanStruct // Copy and paste

newHumanStruct.name = "Bobby"
humanStruct.name // "Bob"

你看到它们的不同之处了么?对拷贝出来的对象的 name 属性的改变并没有影响到原有的 humanStruct 对象。

在类中,当你对一个变量进行拷贝的时候,两个变量都指向内存中的同一个对象。两个中的任何一个变量中的改变都会影响另外一个变量(引用类型)。然而在结构体中,你是通过创建了一个新的对象(值类型)来实现简单的拷贝和复制的。

如果你还没有理解的话,试着把之前那一段再看一遍。如果还是不理解的话,你可以看下我做的这个视频。

结构体 vs 类课程

再见面向对象编程

你可能会很奇怪为什么我所讲的这些好像和面向协议编程的话题一点关系都没有。然而,在我讲使用面向协议编程替换面向对象编程的好处之前,是必须要理解引用类型和值类型的区别的。

使用面向对象编程当然有优点的,但是相对的缺点也存在。

  1. 当时构建子类的时候,你必须继承一些你不需要的属性和方法。你的对象变得不必要的虚胖。

  2. 当时使用了大量的父类(太多继承层级),在不同的类里面跳来跳去编写代码或者修复 bug 都会变得非常棘手。

  3. 因为对象都是指向内存中的同一个空间,如果你创建了一个拷贝,并且对它的属性进行了一点小改动,它会影响到其余的对象。(引用导致的易变性)

顺便说一下,来看一下 UIKit 框架是怎么用面向对象编程来写的。

2015 WWDC_Hideous Structure

如果你作为软件工程师第一次去苹果工作的话,你能使用这些代码么?我的意思是我们开发者在界面层使用中都有过很痛苦的经历。

有人说过面向对象编程就是通过模块化的模式来写意大利面条式的代码。如果你想找到更多关于面向对象编程的缺点的话,看这里的咆哮 1 、咆哮 2 、咆哮 3 、咆哮 4 。

欢迎使用面向协议编程

你可能已经猜到了,和类不一样的是,面向协议编程的基础是值类型。不再是引用了,和你之前看到的金字塔结构不一样,面向协议所提倡的是扁平化和去嵌套的代码。

可能会有点吓到你,我将引出的是苹果的定义。

“协议定义了方法、属性的蓝图…… 然后类、结构体或枚举类型都能够使用协议” — 苹果

你现在唯一需要记住的就是这个词语,“蓝图”。

协议就好像是一个篮球教练,他告诉他的队员该怎么做,但是他却不知道怎么扣篮。

真正的使用面向协议编程

首先,我们来生成人的蓝图。

protocol Human {
	var name: String { get set }
	var race: String { get set }
	func sayHi() 
}

就像你看到的,在协议里是没有真正的”扣篮“。它只会告诉你有那么个东西的存在。顺便说一下,现在你不需要担心 { get set } 。它只是表示你可以改变这个属性的值并能够获取这个属性。除非你用的是一个计算属性话,现在是不用担心的。

现在让我们通过这个协议来写一个韩国人  :kr:  结构体

struct Korean: Human {
	var name: String = "Bob Lee"
	var race: String = "Asian"
	func sayHi() {
 		print("Hi, I'm \(name)") 
 	}
}

一旦这个结构体采用了人类这个协议,它就必须”遵循”这个协议,实现它的所有属性和方法。如果不这么做的话, Xcode 会警报,当然左边也会报错  :rage:  。

就像你看到的,为了满足蓝图你能够自定义所有的协议。你甚至可以建造一个“围墙”。

当然,对美国人  :us:  来说也是一样的。

struct American: Human {
 var name: String = "Joe Smith"
 var race: String = "White"
 func sayHi() { print("Hi, I'm \(name)") }
}

是不是相当酷?看看不再使用 “init” 和 “override” 关键词之后你拥有了多少自由。它是不是开始变得有点意思了?

协议介绍课程

协议继承

如果你想创建一个继承人类协议蓝图的超人协议该怎么办呢?

protocol SuperHuman: Human {
	var canFly: Bool { get set } 
	func punch()
}

现在,如果你想生成一个采用超人协议的结构体或者类的话,你必须也要让它满足人类的协议。

//  超过 9000
struct SuperSaiyan: SuperHuman {
	var name: String = "Goku"
	var race: String = "Asian"
	var canFly: Bool = true
	func sayHi() { 
		print("Hi, I'm \(name)") 
	}
	func punch() { 
		print("Puuooookkk") 
	} 
}

那些理解不了的人,看下这个视频

当然,你可以像在类上面一样遵循多个协议。

// 例子
struct Example: ProtocolOne, ProtocolTwo { }

协议继承课程

协议扩展

现在,这是使用协议最强大的特点了,我不认为我需要讲太多。

// 会说英语的超级动物
protocol SuperAnimal {
	func speakEnglish()
}

给 SuperAnimal 增加一个扩展

extension SuperAnimal {
	func speakEnglish() { 
		print("I speak English, pretty cool, huh?")
	}
}

现在,让我们来创建一个采用 SuperAnimal 协议的类。

class Donkey: SuperAnimal { }
var ramon = Donkey() 
ramon.speakEnglish() //  "I speak English, pretty cool, huh?"

如果你使用扩展的话,你能够给类,结构体和枚举增加默认方法和属性。它难道不神奇么?我发现这是真正的金块啊。

顺带提一下,如果你没有理解的话,你可以看这个

Protocol Extension Lesson

协议作为类型 (Last)

如果我告诉你不需要类型修饰就能够生成一个既包含结构体对象又有类对象的数组呢?

就是这样。

我用为获得雌性配偶而打架的袋鼠来举个例子。如果你不相信我的话,看看这个袋鼠打架

protocol Fightable {
	func legKick() 
}
 
struct StructKangaroo: Fightable {
	func legKick() {
		print("Puuook")
	}
}
 
class ClassKangaroo: Fightable { 
	func legKick() {
		print("Pakkkk") 
	}
}

来,我们生成两个袋鼠对象

let structKang = StructKangaroo()
let classKang = ClassKangaroo()

现在,你可以把它们放到一个数组里了。

var kangaroos: [Fightable] = [structKang, classKang]

厉害了我的哥,这是真的么? :scream:  看看这个

for kang in kangaroos {
	kang.legKick()
}
// "Puuook"
// "Pakkkk"

这个难道不巧妙么?你在面向对象编程中怎么可能实现这个效果... 封面的图片是不是对你来说已经有意义了?面向协议编程纯粹是金子啊。

协议类型课程

现在是免费的,直到它发布之前:)

最后提示

如果你觉得这个教程有用的话,而且你认为我做了一个很棒的事情,请  :heart:  我并且分享到你的社交圈中。我发誓,更多的 iOS 开发者都该应该使用面向协议编程 !我也在努力中,所以才写了这个文章,但是为了更大的影响我需要你的支持。

公开感谢

特别感谢那些参与和指出各处问题的人们。Kilian Költzsch , Erik KrietschÖzgür Celebi , Sanchika Singh RanaFrederick C. Lee ,moh tabi , october hammer , Anthony Kersuzan , Kenneth Trueman , Wilson Balderrama , Rowin , Quang Dinh Luong , Oren Alalouf , Peter Witham , Victor Tong.

预告

这个周六,我将写一些关于在 Swift 3 中如何通过协议实现代理的设计模式的东西。有些人让我写这个,所以我决定听你们的。如果你想要快速更新或者请求我的文章的话,你可以关注我Facebook Page,那里我和我的读者有很多的互动。再见!





原文发布时间为:2017年2月3日

本文来自云栖社区合作伙伴掘金,了解相关信息可以关注掘金网站。
目录
相关文章
|
6月前
|
Swift iOS开发
Swift 语言: 什么是协议(Protocol)?如何实现和使用协议?
Swift 语言: 什么是协议(Protocol)?如何实现和使用协议?
181 2
|
算法 Swift C++
34 Swift为了协议 关联类型
Swift为了协议 关联类型
70 0
|
存储 Swift iOS开发
31 Swift 继续聊聊协议扩展
Swift 继续聊聊协议扩展
107 0
|
6月前
|
设计模式 Swift iOS开发
【Swift开发专栏】Swift中的协议与委托模式
【4月更文挑战第30天】Swift编程语言强调协议与委托模式。协议定义了类型需实现的方法和属性,如`SomeProtocol`示例。遵循协议的类、结构体或枚举需实现协议要求。协议可继承,也可作为类型使用。委托模式让对象间通信更灵活,通过协议实现,如`DataSourceDelegate`示例。实战案例展示了在`UITableView`和自定义下载器中使用委托模式。
107 0
|
4月前
|
存储 安全 Swift
Swift高级特性:泛型与协议
【7月更文挑战第10天】Swift高级特性:泛型与协议增强代码复用与类型安全。泛型允许编写通用代码,如`swap`函数和泛型`Stack`结构体,支持类型约束如`Comparable`。协议定义行为蓝图,类型遵循协议需实现其要求。通过两者结合,构建高效灵活的代码结构。
|
6月前
|
安全 算法 Swift
【Swift开发专栏】Swift中的泛型编程
【4月更文挑战第30天】Swift的泛型允许开发人员创建可重用的组件,操作多种数据类型,无需针对每种类型编写特定代码。本文分为三部分:1) 泛型基本概念,包括类型参数、泛型函数和类型;2) Swift中的泛型实现,如类型推断、关联类型和泛型约束;3) 泛型编程最佳实践,如明确使用场景、选择有意义的类型参数名称和避免过度泛化。通过理解并应用这些概念,开发者能编写出更灵活、安全和高效的代码。
53 2
|
6月前
|
API Swift iOS开发
【Swift开发专栏】Swift中的游戏开发入门
【4月更文挑战第30天】本文介绍了使用Swift进行移动游戏开发的基础知识,包括Apple的开发平台(iOS, macOS)、工具(Xcode)、2D/3D游戏框架(SpriteKit, SceneKit)以及Metal图形API。Swift游戏开发涉及游戏循环、UI设计、逻辑、图形音效和网络编程。通过实例教程展示如何在Xcode中创建2D游戏,从创建项目到实现用户交互、音效和测试。掌握这些基础知识,开发者可快速入门并逐步进阶到更复杂的游戏中。
171 1
|
6月前
|
安全 Swift iOS开发
【Swift 开发专栏】Swift 语言入门指南
【4月更文挑战第30天】Swift是苹果公司的现代编程语言,以其高效、安全和简洁深受喜爱。它融合了类型推断、闭包和泛型等特性,提供强大的内存管理,支持iOS、macOS等多个平台开发。基础语法包括变量、常量、数据类型、运算符和控制流语句。高级特性涵盖函数、闭包、类与结构体、协议以及泛型。学习Swift能为开发者奠定坚实基础。
67 0
|
6月前
|
JSON IDE Swift
Swift语言的实践编程
Swift语言的实践编程
69 3
|
Swift C++ Ruby
32 Swift面向协议编程初探
32 Swift面向协议编程初探
69 0