Swift-Extensions

假设你想给 Swift 标准库 — 比如说Double类型添加额外的方法, 但是你又不知道Double的实现, 所以你不能直接给它添加功能。 你改怎么办呢?

Swift 设计了一个叫做 Extensions 的功能来处理这样的情况。 Extensions 允许你为已经存在的类型添加功能。你可以扩展结构体、枚举和类。

你可以使用如下结构来扩展类型:

  • 计算型属性
  • 新的初始化方法
  • 协议的遵守
  • 新的方法
  • 嵌入类型

扩展一个已经存在的类型


Swift 的扩展不允许你给已存在的类型添加存储属性, 但可以添加计算型属性。

typealias Velocity = Double
extension Velocity {
    var kph: Velocity { return self * 1.60934 }
    var mph: Velocity { return self           }
}

// 为已存在的类型添加要遵守的协议
protocol VehicleType {
    var topSpeed: Velocity { get }
    var numberOfDoors: Int { get }
    var hasFlatbed: Bool   { get }
}

VehicleType声明了三个属性, topSpeed, numberOfDoors 和 hasFlatbed。每个属性都要求遵守该协议的类型只需为该属性实现 getter 方法。遵守该协议的类型需要提供协议中声明的这些属性。

扩展你自己的类型


添加一个自定义的类型:

typealias Velocity = Double
extension Velocity {
    var kph: Velocity { return self * 1.60934 }
    var mph: Velocity { return self }
}
protocol VehicleType {
    var topSpeed: Velocity { get }
    var numberOfDoors: Int { get }
    var hasFlatbed: Bool { get }
}
struct Car {
    let make: String
    let model: String
    let year: Int
    let color: String
    let nickname: String
    var gasLevel: Double {
        willSet {
            precondition(newValue <= 1.0 && newValue >= 0.0,
} }
"New value must be between 0 and 1.")
}

gasLevel 是一个可变的含有属性观察器的存储属性。每次你想要给 gasLevel设置一个新值的时候都会调用 willSet观察器。precondition()函数确保被赋值给 gasLevel 属性的 newValue 在区间 0到1 之内。

给类添加扩展以使其遵守协议


扩展提供了很好的机制来把相关的功能块儿归为一组。在单个扩展中把相关功能片段归为一组可以让你的代码可读性更好, 并且更容易维护。

下面扩展 Car 类型使其遵守 VeicleType 协议。

extension Car: VehicleType {
    var topSpeed: Velocity { return 180   }
    var numberOfDoors: Int { return 4     }
    var hasFlatbed: Bool   { return false }
}

你在extension的主体里面实现了协议的必要属性。每个属性给了一个简单的 getter, 为了方便, 你仅仅返回简单的默认值。

使用扩展给已存在的类添加 initializer


还记得吗, 结构体给了你一个免费的逐个成员初始化函数, 如果你自己每提供的话。如果你想为你的结构体写一个新的 initializer 函数, 但是又不想失去那个免费的逐个成员初始化函数, 你可以使用扩展为你的类型添加一个 initializer 函数。

下面在新的扩展中给Car添加一个initializer 函数:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 132.转换错误成可选值 通过转换错误成一个可选值,你可以使用 try? 来处理错误。当执行try?表达式时,如果...
    无沣阅读 5,092评论 0 3
  • importUIKit classViewController:UITabBarController{ enumD...
    明哥_Young阅读 9,442评论 1 10
  • 136.泛型 泛型代码让你可以写出灵活,可重用的函数和类型,它们可以使用任何类型,受你定义的需求的约束。你可以写出...
    无沣阅读 5,426评论 0 4
  • Hello Word 在屏幕上打印“Hello, world”,可以用一行代码实现: 你不需要为了输入输出或者字符...
    restkuan阅读 8,432评论 0 6
  • 常量与变量使用let来声明常量,使用var来声明变量。声明的同时赋值的话,编译器会自动推断类型。值永远不会被隐式转...
    莫_名阅读 3,273评论 0 1