1.Generics
1.Generic Functions
func swapTwoValues<T>(inout a: T, inout _ b: T) {
let temporaryA = a
a = b
b = temporaryA
}
2.Generic Types
1.使用例子:
struct Stack<Element> {
var items = [Element]()
mutating func push(item: Element) {
items.append(item)
}
mutating func pop() -> Element {
return items.removeLast()
}
}
2.Extending a Generic Type 当用Extension扩展一个泛型类型的时候,不需要再写 Generic Parameter List了,直接用源Type的泛型参数就可以了
extension Stack {
var topItem: Element? {
return items.isEmpty ? nil : items[items.count - 1]
}
}
3.可以给Generic Parameter List添加约束.
1.使用方法
func someFunction<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) {
}
2.有什么用途?
1.比如Dictionary中,key的值必须是Hashable.若key没有遵守Hashable协议,那对于Dictionary来说 根本没法计算key的哈希值,也就根本无法正常工作了
2.比如要判断2个元素是否相等. 在Swift 要使用 == 或 != 来判断两个元素是否相等的话,这两个元素必须实现Equatable. 如果没有显示地给泛型参数一个Equatable协议约束,这两个元素根本无法比较,编译都无法通过 (从这点可以看出,Swift的泛型并不完全像C++一样,C++是编译调用代码的时候直接将泛型参数给替换了,所以显得非常的灵活,但是也相对的不是很安全)
4.(非泛型内容) 可以给Protocol添加一个Associated Types 来实现类似于 泛型的功能
使用方法:
protocol Container {
typealias ItemType
mutating func append(item: ItemType)
var count: Int { get }
subscript(i: Int) -> ItemType { get }
}
struct ArrayList: Container {
var items = [Int]()
// conformance to the Container protocol
typealias ItemType = Int //由于Swift的推断机制,这句话其实可以省略
mutating func append(item: Int) {
self.items.append(item)
}
var count: Int {
return items.count
}
subscript(i: Int) -> Int {
return items[i]
}
}
补充1:还可以加上泛型参数,然后把所有Int换成那个泛型参数即可
补充2:由于系统自带的Array已经实现了这几个功能,所以直接扩展(extension)Array 让Array遵守Container协议即可,多余的代码不用写.
5.Where Clauses
func allItemsMatch<
C1: Container, C2: Container
where C1.ItemType == C2.ItemType, C1.ItemType: Equatable>//ItemType是在Container中声明的
(someContainer: C1, anotherContainer: C2) -> Bool{
//TODO
}
2.Access Control (访问控制)
1.Swift提供了三种访问权限 (为了简洁,下面用实体来代替properties, types, functions等等)
1.Public access : 修饰的实体 既可以在 自己模块内的任何源代码文件中访问,也可以在 其他导入自己模块的源代码中访问.最好当说明接口的时候使用这个权限
2.Internal access: 修饰的实体 可以在 自己模块内的任何源代码文件中访问,但是不能在 其他导入自己模块的源代码中访问.最好当定义模块内的内部结构体的时候使用这个权限
3.Private access:修饰的实体 只能在定义自己的源代码文件中访问.最好当想隐藏一个功能的特定片段的实现细节的时候使用这个权限.
注意:在Swift中,private不同于Java中的private. Swift的private的范围是整个源代码文件.
2.Swift中Access Level遵守一个综合的规定准则: 实体不能定义在另一个比它访问等级更低的实体中. 比如:
1.一个public变量不能定义在一个internal/private的type中
2.一个function不能比它的参数/返回值的访问等级高
3.如果不设置访问等级,那么默认的访问等级是 internal access.
4.type的访问等级会影响type内部的成员的默认访问等级:
1.type是private,那么type内部的成员的默认访问等级是private
2.type是internal/public,那么type内部的成员的默认访问等级是internal
5.Tuple types的访问等级来自它里面的成员,取成员里面最小的访问等级作为自己的访问等级(不能显式声明,只能被推断出)
6.Function Types的访问等级 取形参和返回值中最小的访问等级作为自己的访问等级 (可以显式声明,但是有效无效要看情况)
7.Enumeration Types 内部各个的访问等级和 enum 声明的访问等级相同
8.Raw Values 和 Associated Values 的访问等级必须不小于enumeration
9.subclass的访问等级不能比superclass的大.但是重写的方法/属性 的访问等级可以比原来的大(仔细想想就知道为什么了,没有小的必要啊). 就算原来的方法的访问等级是private 只要这个调用发生在同一源文件,子类的成员也能调用原方法.(这个的原因其实就是简单的访问等级的作用范围 看2.1)
10.getter 和 setter .
1.setter的访问等级可以比getter的低.
2.声明方式 (不管是 computed property 还是 stored property 都是这样)
public private(set) var a: NSString
11.initializer的访问等级
1.一般的自定义initializers的访问等级小于等于type.但是有一个例外,那就是required initializer(注意:只有class才有required initializer).required initializer的访问等级必须和class的访问等级相同
2.和函数相同,构造方法的参数的访问等级不能小于构造方法的访问等级
3.Default Memberwise Initializers . 如果结构体中有任何一个stored property是private的,那么Memberwise Initializers的访问等级也是private,除此以外,Memberwise Initializers的访问等级都是internal
12.Protocol的访问等级:
1.Protocol里面声明的所有内容的访问等级永远和Protocol的访问等级相同.
2.如果有一个Protocol继承自另外一个Protocol,那么这个Protocol的访问等级不能大于父Protocol.
3.遵守该Protocol的type对于Protocol的实现 的访问等级至少拥有protocol的访问等级.
13.Extension
1.Extension中新声明的功能 默认地和源type的访问等级类似(如果源type是public/internal,那么它们访问等级是internal,如果源是private,那么它们也是private).
2.你可以显式地声明Extension内功能的访问等级(只能小不能大).也可以显式地声明Extension的访问等级(只能小不能大),这个访问等级作为Extension内功能默认的访问等级,当然这个功能的默认访问等级还能够被显式声明为更低的访问等级
3.如果你用extension将一个已存在的type遵守一个新的协议,那么你不能显式地声明这个extension.相反,这个默认地访问等级是来自于protocol
3.不同于C,在Swift中,默认情况下算术操作如果溢出Swift会出错.如果想进行溢出运算 必须使用 溢出操作(&+等).所有的溢出操作都必须以&开头
4.Swift可以重载基本的操作符用于structure,enumeration,class的运算.