扩展
特点
- Swift的扩展与OC的Category类似,只是swift中的扩展没有名字.
- 扩展并不是派生子类,因此不支持重写
- 可以使一个已有类型符合一个或者多个协议
语法定义
修饰符可以省略,或者是private,internal,public其中之一,类型可以是枚举,结构体和类其中之一1
2
3[修饰符]extension已有类型{
//添加新功能
}
1 | [修饰符]extension已有类型:协议1,协议2{ |
添加属性
使用扩展可以添加3种属性:类型存储属性,实例计算属性,类型计算属性,就是不能添加实例存储属性1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43extension String {
static var data:[String:Any] = [:]
var length:Int{
get{
return self.characters.count
}
set{
let originLength = self.characters.count
//如果新设置的长度大于字符串原有长度,在字符串后面添加空字符
if newValue > originLength {
for _ in 1...newValue - originLength {
self += " "
}
}
//如果新设置的长度小于字符串原有长度,将后面多余的字符截断
else if newValue < originLength {
var tmp = ""
var count = 0
for ch in self.characters {
tmp = "\(tmp)\(ch)"
count++
//如果已经拼接了newValue个字符,跳出循环
if count == newValue {
break
}
}
self = tmp
}
}
}
}
String.data["swift"] = 89
String.data["OC"] = 92
print(String.data)
var s = "jike.org"
//通过length输出字符串的长度
print(s.length)
//通过设置length属性,截断String后面多出来的字符
//s.length = 5
//print(s)
//通过设置length属性,在string后面补充空格
s.length = 10
print(s)
添加方法
1 | extension String { |
添加可变方法
类不可以定义可变方法,不能通过扩展来为类添加可变方法
1 | extension Array { |
添加下标
1 | extension String { |
添加构造器
- 没有构造器,系统会提供默认的,
- 已经定义了,系统就不会提供构造器
- 想要他们并存,就需要扩展,通过扩展添加的构造器,不会影响原有的构造器
1 | //定义一个结构体 |
添加嵌套类型
1 | extension String { |
Protocol - 规范和实现的分离 & 松耦合的设计
一个协议可以有多个直接父协议,但协议只能继承协议,不能继承类
[修饰符]protocol协议名:父协议1,父协议2,...{
//协议内容
}
协议定义了一种规范,不提供任何实现
protocol Souschef {
func chop(vegetable: String) -> String
func rinse(vegetable: String) -> String
}
协议的实现
class Roommate: Souschef, Equatable {
var hungry = true
var name: String
init(hungry: Bool, name: String) {
self.hungry = hungry
self.name = name
}
func chop(vegetable: String) -> String {
return "She's choppin' \(vegetable)!"
}
func rinse(vegetable: String) -> String {
return "The \(vegetable) is so fresh and so clean"
}
}
安装一个适用于对象比较的协议
func ==(lhs: Roommate, rhs: Roommate) -> Bool {
return lhs.name == rhs.name && lhs.hungry == rhs.hungry
}
var roomie = Roommate(hungry: true, name: "Jennifer")
var theBestRoomie = Roommate(hungry: true, name: "Jennifer")
roomie == theBestRoomie
A protocol is also a type
class DinnerCrew {
var members: [Souschef]
init(members: [Souschef]) {
self.members = members
}
}
class RandomPasserby: Souschef {
var name: String
init(name: String){
self.name = name
}
func chop(vegetable: String) -> String {
return "She's choppin' \(vegetable)!"
}
func rinse(vegetable: String) -> String {
return "The \(vegetable) is so fresh and so clean"
}
}
var newFriend = RandomPasserby(name: "Dave")
var motleyDinnerCrew = DinnerCrew(members:[newFriend, roomie])
协议语法和属性要求
1 | class var 属性名:类型{get set} |
- class可有可无。如果有class关键字,说明为类型属性,否则为实例属性。不可以使用static代替class
- get和set部分:只需要写get,set即可,无须提供实现,set可有可无
- 协议多继承,弥补了类单继承的不足
- 协议中使用class关键字定义类型属性,但值类型中依然使用static定义类型属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41protocol Strokable{
var strokeWidth:Double {get set}
}
protocol Fullable{
var fullColor:Color? {get set}
}
//定义一个枚举作为协议属性的类型
enum Color {
case Red,Green,Blue,Yellow,Cyan
}
protocol HasArea:Fullable,Strokable {
var area:Double{get}
}
protocol Mathable{
//这里怎么用static? 和说明上不一样哦
static var pi: Double {get}
static var e: Double {get}
}
//让Rect实现2个协议
struct Rect:HasArea,Mathable{
var width:Double
var height:Double
init(width:Double,height:Double){
self.width = width
self.height = height
}
//使用存储属性实现Fullable协议的fullColor属性
var fullColor:Color?
//使用存储属性实现Strokable协议的strokeWidth属性
var strokeWidth:Double = 0.0
//使用存储属性实现HASAREA协议要求的area属性
var area: Double{
get{
return width * height
}
}
//通过存储属性实现Mathable协议要求的两个类型属性
//虽然协议中使用class关键字定义类型属性,但值类型中依然使用static定义类型属性
static var pi:Double = 3.14159
static var e:Double = 2.71626
}