Swift笔记 - 12.访问控制、初始化器、扩展、weak、unowned、Autorelease
Swift笔记 - 12.访问控制、初始化器、扩展、weak、unowned、AutoreleasePool
访问控制
- 在访问权限控制这块,Swift提供了5个不同的访问级别(以下是从高到低排列,实体指被访问级别修饰的内容) - open:允许在定义实体的模块、其他模块中访问,允许其他模块进行继承、重写(open只能用在类、类成员上)
- public:允许在定义实体的模块、其他模块中访问,不允许其他模块进行继承、重写
- Dinternal:只允许在定义实体的模块中访问,不允许在其他模块中访问
- fileprivate:只允许在定义实体的源文件中访问
- private:只允许在定义实体的封闭声明中访问
 
- 绝大部分实体默认都是internal级别
访问控制级别的使用准则
- 一个实体不可以被更低访问级别的实体定义,比如 - 变量\常量类型 ≥变量\常量
- 参数类型、返回值类型 ≥函数
- 父类 ≥子类
- 父协议 ≥子协议
- 原类型 ≥typealias
- 原始值类型、关联值类型 ≥枚举类型
- 定义类型A时用到的其他类型 ≥类型A
 
- 变量\常量类型 
- 炎型的访问级别会影哈成员(属性、方法、初始化器、下标),嵌套炎型的默认访问圾别 - 一般情况下,类型为private或fileprivate那么成员private或fileprivate
- 一般情況下,类型为internal或public,那么成员\嵌套类型默认是internal
 
- 一般情况下,类型为
public class PublicClass {
    public var p1 = 8 // public
    var p2 = 8 // internal
    fileprivate func f1() {} // fileprivate
    private func f2() {} // private
}
class InnerClass { // internal
    var p = 0 // internal
    fileprivate func f1() {} //fileprivate
    private func f2() {} //private
}
fileprivate class PilePrivateClass ( // fileprivate
    func 110) 0) / fileprivate
    private func 12() { // private
}
private class PrivateClass { // private
    func f() {} // private
}
-  子类重写的成员访问级别必须 ≥父炎的成员访向级别
-  getter、setter默认自动接收它们所属环境的访问级别- 可以给setter单独设置一个比getter更低的访问坡别,用以限制写的权限
 
- 可以给
fileprivate(set) public var nun = 10
class Person {
    private(set) var age = 0
    fileprivate(set) public var weight: Int
    set {}
    get { 10 }
    internal(set) public subscript(index: Int) -> Int (
    set {}
    get { index }
}
初始化器
- 如果一个public类想在另一个横块调用编泽生成的默认无参初始化器,必须显式提供pubLic的无參初始化器- 因为public类的默认初始化器是internal级别
 
- 因为
-  required初始化器必须跟它所履类拥有相同的访问级别
- 如果结构体有private\fileprivate的存储实例属性,那么它的成员初始化器也是private fileprivate- 否则默认就是internal
 
- 否则默认就是
扩展(Extension)
- Swift中的扩展,有点类似于OC中的分类(Category)- 扩展可以为枚举、结构体、类、协议添加新功能
- 可以添加方法、计算属性、下标、(便捷)初始化器、嵌套类型、协议等等
 
- 扩展不能办到的事情 - 不能覆盖原有的功能
- 不能添加存储属性,不能向已有的属性添加属性观察器
- 不能添加父类
- 不能添加指定初始化器,不能添加反初始化器
 
Extension的计算属性、下标、方法、嵌套类型
extension Double {
    var km: Double { self * 1 000.0 }
    var m: Double { self }
    var dm: Double $ self / 100.0
    var cm: Double { self / 10.0 }
    var mm: Double { self / 1 000.0 }
}
extension Array {
    subscript(nullable idx: Int) -> Element? {
        if (startIndex..<endIndex).contains(idx) {
            return self[idx]
        }
        return nil
    }
}
extension Int {
    func repetitions(task: () -> Void) {
        for _ in 0..<self { task() }
    }
    mutating func square() -> Int {
        self = self * self
        return self
    }
    enum Kind { case negative, zero, positive }
    var kind: Kind {
        switch self {
            case 0: return .zero
            case let x where x > 0: return .positive
            default: return .negative
        }
    }
    subscript(digitIndex: Int) -> Int {
        var decimalBase = 1
        for _ in 0..<digitIndex { decimalBase *= 10 }
        return (self / decimalBase) % 10
    }
}
协议、初始化器
class Person {
    var age: Int
    var name: String
    init(age: Int, name: String) {
        self.age = age
        self.name = name
    }
}
extension Person : Equatable {
    static func == (left: Person, right: Person) -> Bool {
        left.age == right.age && left.name == right.name
    }
    convenience init() {
        self.init(age: 0, name: "'")
    }
}
struct Point {
    var x: Int = 0
    var y: Int = 0
}
extension Point {
    init(_ point: Point) {
        self.init(x: point.x, y: point.y)
    }
}
var p1 = Point()
var p2 = Point(x: 10)
var p3 = Point(y: 20)
var p4 = Point(x: 10, y: 20)
var p5 = Point(p4)
- 如果希望自定义初始化器的同时,编译器也能够生成默认初始化器
- 可以在扩展中编写自定义初始化器
- 类遵守协议实现的required初始化器,不能写在扩展中
使用扩展来遵守协议,也可以使用扩展来为协议添加方法实现
- 如果一个类型已经实现了协议的所有要求,但是还没有声明它遵守了这个协议 - 可以通过扩展来让它遵守这个协议
 
protocol TestProtocol {
    func test()
}
class TestClass {
    func test() {
        print("test")
    }
}
extension TestClass : TestProtocol {}
- 编写一个西数,判断一个整数是否为奇数? func isOdd<T: BinaryInteger>(_ i: T) -> Bool { 1 % 2 != 0 }
- 扩展可以给协议提供默认实现,也间接实现『可选协议』的效果
- 扩展可以给协议扩态『协议中从末声明过的方法』
protocol TestProtocol {
    func test1()
}
extension TestProtocol {
    func test1() {
        print ("TestProtocol test1")
    }
    func test2() {
        print ("TestProtocol test2")
    }
}
class TestClass : TestProtocol {}
var cls = TestClass()
cls.test1() // TestProtocol test1
cls.test2() // TestProtocol test2
var cls2: TestProtocol = TestClass()
cls2.test1() // TestProtocol test1
cls2.test2() // TestProtocol test2
class TestClass : TestProtocol {}
func test1() { print ("TestClass test1") }
func test2() { print ("TestClass test2") }
var cls = TestClass()
cls.test1() // TestClass test1
cls.test2() // TestClass test2
var cls2: TestProtocol = TestClass()
cls2.test1() // TestClass test1
cls2.test2() // TestProtocol test2
extension BinaryInteger {
    func isOdd() -> Bool { self % 2 != 0 }
}
var age: Int8 = 10
print(age.isOdd())
print(10.is0dd())
print((-3).isodd())
弱引用
-  跟OC一样,Swift也是采取基于引用计数的ARC内存管理方案(针对堆空间) 
- Swift的ARC中有3种引用 - 强引用(strong reference):默认情况下,引用都是强引用
 
- 强引用(
- 弱引用(weak reference):通过weak定义弱引用- 必须是可选类型的var,因为实例销毁后,ARC会自动将弱引用设置为nil
- ARC自动给弱引用设置nil时,不会触发属性观察器
 
- 必须是可选类型的var,因为实例销毁后,ARC会自动将弱引用设置为
- 无主引用(unowned reference):通过unowned定义无主引用- 不会产生强引用,实例销段后仍然存储着实例的内存地址(类似于OC中的unsafe_unretained)
- 试图在实例销毁后访问无主引用,会产生运行时错误(野指针)
- •Fatal error: Attempted to read an unowned reference but object 0x0 was already deallocated
 
- 不会产生强引用,实例销段后仍然存储着实例的内存地址(类似于OC中的
weak、unowned的使用限制
- weak、- unowned只能用在类实例上面
protocol Livable : AnyObject {}
class Person {}
weak var pO: Person?
weak var p1: AnyObject?
weak var p2: Livable?
unowned var p10: Person?
unowned var p11: AnyObject?
unowned var p12: Livable?
AutoreleasePool
public func autoreleasepool<Result>(invoking body: () throws -> Result) rethrows -> Result
autoreleasepool {
    let p = MJPerson(age: 20, name: "Jack")
    p.run()
}