扩展就是向一个已有的类、结构体、枚举类型或协议类型添加新功能。而且还包括在没有权限获取原始源代码的情况下扩展类型的能力(逆向建模)。
swift中的扩展可以:
- 添加计算型属性和计算型静态属性
- 定义实例方法和类型方法
- 提供新的构造器
- 定义下标
- 定义和使用新的嵌套类型
- 使一个已有类型符合某个协议
在swift中,甚至都可以对一个协议进行扩展,提供协议需要的实现,或添加额外的功能。
注意: 扩展是对一个类型添加新的功能,但是不能重写已有的功能。
一、扩展语法
声明一个扩展使用关键字extension
:
extension SomeType {
// 加到SomeType的新功能
}
给已有类型扩展,是其能够适配一个或多个协议,而这种情况协议的名字应该完全按照类或结构体的名字方式进行书写:
extension SomeType:SomeProtocol, AnotherProctocal {
// 协议具体实现
}
二、计算型属性
扩展可以向已有类型添加计算型实例属性和计算型类型属性:
// 功能: 给系统的Double类型添加3个计算型实例属性,方便单位的转换,方便阅读
// 默认设置的米为单位,即Double型的值1.0,表示就是“1米”
extension Double {
// 千米
var km:Double {
return self * 1_000.0;
}
// 米
var m:Double {
return self;
}
// 厘米
var cm:Double {
return self / 100.0;
}
}
// 身高183cm
let myHeight = 183.cm;
print("我的身高\(myHeight.m)米");
输出结果:
我的身高1.83米
注意: 扩展可以添加新的计算属性,但不可以添加存储属性,也不可以向已有属性添加属性观察器!!!
三、构造器
扩展可以向已有类型添加新的构造器,这让可以扩展其他类型,将自己定制类型作为构造器参数,或者提供该类型的原始实现中没有包含的额外初始化选项。
扩展能向类中添加新的便利构造器,但不能向类中添加新的指定构造器或析构器,即是说指定构造器和析构器必须总是由原始类实现来提供。
/**
矩形结构体Rect
矩形大小结构体Size
矩形位置结构体Point
*/
// 矩形大小
struct Size {
var width = 0.0, height = 0.0;
}
// 矩形位置
struct Point {
var x = 0.0, y = 0.0;
}
// 矩形位置以及大小
struct Rect {
// 位置
var origin = Point();
// 大小
var size = Size();
}
// 使用结构体的成员逐一构造器
// 矩形是位置在原点(0,0),大小(3,3)
// 如下图所示
let myRect = Rect(origin: Point(x: 0.0, y: 0.0),
size: Size(width: 3.0, height: 3.0));
// 给Rect结构体扩展一个构造器,使用矩形的中心点和大小表示结构体
extension Rect {
// 中心点center 大小size
init(center: Point, size: Size) {
let originX = center.x - (size.width / 2);
let originY = center.y - (size.height / 2);
self.init(origin: Point(x: originX,y: originY),
size: size);
}
}
// 位置为(0,0),大小为(4,4),这个矩形的中心点位置是(2,2)
// 如下图所示
let myRect = Rect(center: Point(x: 2, y: 2),
size: Size(width: 4, height: 4));
// 验证位置是不是(0,0)
print(myRect.origin.x)
print(myRect.origin.y)
输出结果:
0.0
0.0
四、方法
扩展可以向已有类型添加新的实例方法和类型方法:
// 给Int类型扩展一个新实例方法
extension Int {
// 扩展一个打印遍历方法
func helloFunc() {
for i in 1...self {
print("\(i)-hello Swift!")
}
}
}
var num:Int = 3;
num.helloFunc();
输出结果:
1-hello Swift!
2-hello Swift!
3-hello Swift!
五、下标
扩展可以向已有类型添加新下标:
// 给Int添加一个下标
extension Int {
// 扩展下标,获取数据中对应的位数的数字
// 例如123, 123[0]表示取出个位数字3
// 例如789, 789[2]表示取出百位数字7
subscript(var index:Int) -> Int {
// 临时变量
var temp = 1;
while index > 0 {
// 是取出第几位
// 例如取出百位,temp就是100;取出10位,temp就为10
temp *= 10;
index -= 1;
}
return (self / temp) % 10;
}
}
var num = 123456;
print(num[0]);
num = 784312312;
print(num[2]);
输出结果:
6
3