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()
}