Swift的协议默认实现


    • 继承和组合的缺点
    • 带默认实现的协议
    • 小结

继承和组合的缺点

在开发工作中,继承总是用来在多个类之间共享代码。

设想一个场景,一个人类,可以说话和睡觉,而一个Worker,除了上述功能,还可以工作。

解决方案很简单,我们可以 Person 和 Worker 之间建立继承关系:

class Person {
    func say() {
        print("hello")
    }
    func sleep() {
        print("I‘m sleeping")
    }
}
class Worker: Person {
    func work() {
        print("I‘m carrying bricks")
    }
}

在随后的开发中,可能一个新的类型 Robot,也可以工作了,这个时候我们不能使用 Worker 了,因为很明显, Robot不可能同时是一个Person。

解决这个问题,我们可能尝试组合的方式,通过公共类管理 work 行为:

class WorkManager {
    func work() {
        print("I‘m carrying bricks")
    }
}
class Worker: Person {
    let workManager = WorkManager()
    func work() {
        workManager.work()
    }
}
class Robot: Machine {
    let workManager = WorkManager()
    func work() {
        workManager.work()
    }
}

这样做的缺点也显而易见,代码虽然复用了,可是类结构也变的臃肿,每次都要引用 WorkManager 。

带默认实现的协议

在Swift2.0里在定义一个协议protocol时,还能使用extension给它的某些方法做默认实现:

protocol Workable {
  func work()
}
extension Workable {
  func work() {
    print("I‘m carrying bricks")
  }
}

有了上面的代码,当你创建一个遵从 Workable 协议的类或者是结构体时,就能获得 work() 方法

这只是一个默认的实现方式。因此你可以在需要的时候重新定义这个方法;如果不重新定义的话,会使用这个默认方法。

使用这种方式,可以大大简化我们的代码,我们甚至什么都不需做,指定继承关系就完成了工作:

class Worker: Person, Workable {
}
class Robot: Machine, Workable {
}
...
let worker = Worker()
let robot = Robot()
worker.work() // I‘m carrying bricks
robot.work() // I‘m carrying bricks

当然我们也可以设定协议依赖的数据,比如work依赖对象的名字:

protocol Workable {
    var name: String { get }
    func work()
}
extension Workable {
  func work() {
    print("\(name) is carrying bricks")
  }
}
class Worker: Person, Workable {
    var name: String
    init(name: String) {
        self.name = name
    }
}
...
let worker = Worker("Tiezhu")
worker.work() // Tiezhu is carrying bricks

现在可以按照功能重新划分protocol,并开启积木模式了, 首先拆分 Person :

protocol Sayable {
    var words: String { get }
    func say()
}
extension Sayable {
  func say() {
    print("\(words)")
  }
}
protocol Sleepable {
    var name: String { get }
    func sleep()
}
extension Sleepable {
  func sleep() {
        print("\(name) is sleeping")
  }
}

enjoy it :

class Person: Sayable, Sleepable {}
class Worker: Person, Workable {
    var name: String
    var words = "hello"
    init(name: String) {
        self.name = name
    }
}
class Robot: Sayable, Workable {
    var name: String
    var words = "..."
    init(name: String) {
        self.name = name
    }
}
class Cat: Sayable, Sleepable {
    var name: String
    var words = "meow~"
    init(name: String) {
        self.name = name
    }
}
...
let tiezhu = Worker(name: Tiezhu)
tiezhu.work() // Tiezhu is carrying bricks
let robot = Robot(name: T1000)
robot.work() // T1000 is working
let feifei = Cat(name: "feifei")
feifei.say() // meow~

小结

不同于OC, Swift里大量使用了protocol, 在OC中,protocol仅限用于NSObject的子类, 而Swift则不同, protocol可以被任何类型实现,点进Swift的各个基本类型,可以看到它们都实现了各式协议,这使它们功能比其他的语言更加强大,拓展性更是如此。 Swift 的 extension 也比OC的强大的多,protocol 和 extension配合起来, 做到了更大的灵活性,实现更加强大的功能, 比起继承和组合更加有效。

                                                杏树林研发 王儒林
时间: 2024-08-03 09:13:08

Swift的协议默认实现的相关文章

swift 用协议实现代理传值功能

1.功能简介 RootViewController中用个lable和一个按钮,点击按钮跳转到模态窗口.在模态窗口中有个TextField和一个按钮,输入文字点击关闭模态按钮后跳转到RootViewController,并改变其label为输入的值. 2.实现思路 ModelViewController中定义一个成员变量,成员变量有个能改变label值的函数,通过在ModelViewController中调用该函数从而改变RootViewController中label的值,因为ModelView

Swift学习——A Swift Tour 协议和扩展

Protocols and Extensions Protocols  协议的使用 使用关键字 protocol 定义一个协议 protocol ExampleProtocol { var simpleDescription: String { get } mutating func adjust() } 类,枚举和结构体都可以实现协议 class SimpleClass: ExampleProtocol { var simpleDescription: String = "A very sim

InstallShield 2010 Basic MSI工程许可协议默认允许

在Property Manager(具体位置:Installation Designer/Behavior and Logic/Property Manager)中修改AgreeToLicense属性值为Yes,InstallShield 2010中默认为No InstallShield 2010 Basic MSI工程许可协议默认允许

Swift中协议的简单介绍

熟悉objective-c语言的同学们肯定对协议都不陌生,在Swift中苹果将 protocol 这种语法发扬的更加深入和彻底.Swift语言中的 protocol 不仅能定义方法还能定义属性,配合 extension 扩展的使用还能提供一些方法的默认实现,而且不仅类可以遵循协议,现在的枚举和结构体也能遵循协议了.基于此本文从 1,协议中定义属性和方法 , 2,协议的继承.聚合.关联类型 , 3,协议的扩展 , 4,Swift标准库中常见的协议 , 5,为什么要使用协议 5个方面结合自身的学习经

窥探Swift之协议(Protocol)和委托代理(Delegate)回调的使用

协议与委托代理回调在之前的博客中也是经常提到和用到的在<Objective-C中的委托(代理)模式>和<iOS开发之窥探UICollectionViewController(四) --一款功能强大的自定义瀑布流>等博客内容中都用到的Delegate回调.说到协议,在Objective-C中也是有协议的,并且Swift中的协议和Objc中的协议使用起来也是大同小异的,在Java等现代面向对象编程语言中有接口(Interface)的概念,其实和Swift中或者Objc中的Protoco

利用Swift之协议语法实现页面间的传值功能

随着Swift 新开发语言的发布,又随着Xcode6.0.1的正式发布,利用swift编写iOS代码迫在眉睫,笔者在使用Objective-C开发近三年以来,对这种优雅的语法深感赞叹,下面我将对比式的实现一个页面传值的demo,使用语法是swift,页面传值是学习iOS初期必修的demo,因为涉及一个非常难懂的语法:协议和委托,这里涉及的swift语法和一些基本操作我不在一一赘述,如果方便可下载IT面试宝典APP,里面有对其详细介绍,那就开门见山吧,用代码实现以下功能: 1,创建Swift工程,

Swift - AppDelegate.swift类中默认方法的介绍

项目创建后,AppDelegate类中默认带有如下几个方法,具体功能如下: 1,应用程序第一次运行时执行 这个方法只有在App第一次运行的时候被执行过一次,每次App从后台激活时都不会再执行该方法. (注:所有一般我们都在这里获取用户许可,比如本地消息推送的许可等) 1 2 3 4 func application(application: UIApplication,     didFinishLaunchingWithOptions launchOptions: [NSObject: Any

各常用协议默认端口一览

协议名称 默认端口号 tcp或udp http 80 tcp https 443 tcp/udp smtp 25 tcp imap 143 tcp ftp 21 tcp pop3 110 tcp lotusnote 1352 tcp vnc 5900 tcp msSQL server monitor 1434 tcp/udp msSQL server 1433 tcp Citrix ICA(old) 1494 tcp MSN 1863 tcp Sinfor DNet 856 tcp Netmee

swift protocol(协议) associatedtype关联类型

定义一个协议时,有的时候声明一个或多个关联类型作为协议定义的一部分将会非常有用.关联类型为协议中的某个类型提供了一个占位名(或者说别名),其代表的实际类型在协议被采纳时才会被指定.你可以通过 associatedtype 关键字来指定关联类型.比如使用协议声明更新cell的方法: //模型 struct Model { let age: Int } //协议,使用关联类型 protocol TableViewCell { associatedtype T func updateCell(_ da