JHHK

欢迎来到我的个人网站
行者常至 为者常成

15_01、访问控制、内存管理(一)

目录

访问控制

/**
 模块:指的是独立的代码单元,框架或应用程序会作为一个独立的模块来构建和发布。在 Swift 中,一个模块可以使用 import 关键字导入另外一个模块
 在访问权限控制这块,Swift提供了5个不同的访问级别(以下是从高到低排列, 实体指被访问级别修饰的内容)
 open:允许在定义实体的模块、其他模块中访问,允许其他模块进行继承、重写(open只能用在类、类成员上)
 public:允许在定义实体的模块、其他模块中访问,不允许其他模块进行继承、重写
 internal:只允许在定义实体的模块中访问,不允许在其他模块中访问
 fileprivate:只允许在定义实体的源文件中访问
 private:只允许在定义实体的封闭声明中访问
 绝大部分实体默认都是internal 级别
 */

open class accessClass{}        //所有模块可访问 可继承可重写
public class accessClass1{}     //所有模块可访问 其它模块不可继承不可重写
internal class accessClass2{}   //只有本模块可访问
fileprivate class accessClass3{}//只有当前文件可访问
private class accessClass4{}    //只有当前作用域可访问 当其位于文件的全局作用域时 与 filePrivate 相同


/**
 一个实体不可以被更低访问级别的实体定义,比如
 参数类型、返回值类型 ≥ 函数
 父类 ≥ 子类
 父协议 ≥ 子协议
 原类型 ≥ typealias
 原始值类型、关联值类型 ≥ 枚举类型
 定义类型A时用到的其他类型 ≥ 类型A
 ......
 */
//1、变量\常量类型 ≥ 变量\常量
let openvar  = accessClass()    //常量openvar为internal 类型accessClass为open
let openvar1 = accessClass1()   //常量openvar为internal 类型accessClass为public
let openvar2 = accessClass2()   //常量openvar为internal 类型accessClass为internal
//let openvar3 = accessClass3() //编译报错 openvar3权限为internal accessClass3权限为 fileprivarte
//let openvar4 = accessClass4() //编译报错 openvar4权限为internal accessClass4权限为 privarte
//2、元祖的访问控制权限
/*元组类型的访问级别是所有成员类型中最低的那个*/
internal   struct ACCDog { }
fileprivate class ACCPerson { }
//(ACCDog, ACCPerson) 的访问级别是 fileprivate
fileprivate var data1: (ACCDog, ACCPerson) = (ACCDog(),ACCPerson())
private     var data2: (ACCDog, ACCPerson) = (ACCDog(),ACCPerson())
//3、泛型类型
/**泛型类型的访问级别是 类型的访问级别 以及 所有泛型类型参数的访问级别 中最低的那个*/
internal class ACCCar3 {}
fileprivate class ACCDog3 {}
public class ACCPerson3<T1, T2> {}
// ACCPerson3<ACCCar3, ACCDog3>的访问级别是fileprivate
fileprivate var p = ACCPerson3<ACCCar3, ACCDog3>()
//4、成员、嵌套类型
/**
 类型的访问级别会影响成员(属性、方法、初始化器、下标)、嵌套类型的默认访问级别
 一般情况下,类型为fileprivate或private,那么成员\嵌套类型默认也是fileprivate或private
 一般情况下,类型为public或internal,那么成员\嵌套类型默认是internal
 */
public class PublicClass {   // public
    public var p1 = 0        // public
    var p2 = 0               // internal
    fileprivate func f1() {} // fileprivate
    private func f2() {}     // private
}


class InternalClass {        // internal
    var p = 0                // internal
    fileprivate func f1() {} // fileprivate
    private func f2() {}     // private
}

fileprivate class FilePrivateClass { // fileprivate
    func f1() {}                     // fileprivate
    private func f2() {}             // private
}

private class PrivateClass { // private
    func f() {}              // private
}
//5、成员的重写
/**
 子类重写成员的访问级别必须 ≥ 子类的访问级别,或者 ≥ 父类被重写成员的访问级别
 父类的成员不能被成员作用域外定义的子类重写
 */
public class ACCPerson5 {

    //父类的成员不能被成员作用域外定义的子类重写
    private var age: Int = 0
    
    fileprivate var height:Int = 180
    
    public class ACCStudent5 : ACCPerson5 {
        override var age: Int { //internal
            set {}
            get {10}
        }
    }
}



public class ACCStudent5 : ACCPerson5 {
//    override var age : Int{
    var age : Int{
        set {}
        get {10}
    }
    
    override var height: Int{
        set{}
        get{180}
    }
}


func ACCPerson5Test() -> Void {
    let stu = ACCPerson5.ACCStudent5()
    print("stu.age = ",stu.age)
    
}
//6、下面代码能否编译通过
/**
 直接在全局作用域下定义的private等价于fileprivate
 */

//6_0可以编译通过
private class ACCPerson6 {}
fileprivate class ACCStudent6:ACCPerson {}

//6_1可以编译通过
private struct ACCDog61 {
    var age: Int = 0
    func run() {}
}
fileprivate struct ACCPerson61 {
    var dog: ACCDog61 = ACCDog61()
    mutating func walk() {
        dog.run()
        dog.age = 1
    }
}


//6_2不可以编译通过
private struct ACCDog62 {
    private var age: Int = 0
    private func run() {}
}
fileprivate struct ACCPerson62 {
    var dog: ACCDog62 = ACCDog62()
    mutating func walk() {
//        dog.run()     //无法访问'run' is inaccessible due to 'private' protection level
//        dog.age = 1   //无法访问'age' is inaccessible due to 'private' protection level
    }
}
//7、getter、setter
/**
 getter、setter默认自动接收它们所属环境的访问级别
 可以给setter单独设置一个比getter更低的访问级别,用以限制写的权限
 */
fileprivate(set) public var num = 10

class ACCPerson7 {
    private(set) var age = 0
    
    fileprivate(set) public var weight: Int {
        set {}
        get { 10 }
    }
    
    internal(set) public subscript(index: Int) -> Int {
        set {}
        get { index }
    }
}
//8、初始化器
/**
如果一个public类想在另一个模块调用编译生成的默认无参初始化器,必须显式提供public的无参初始化器
因为public类的默认初始化器是internal级别
 
required初始化器 ≥ 它的默认访问级别
 
如果结构体有private\fileprivate的存储实例属性,那么它的成员初始化器也是private\fileprivate
否则默认就是internal
 */
//9、枚举类型的case
/*
不能给enum的每个case单独设置访问级别
每个case自动接收enum的访问级别
public enum定义的case也是public
*/
//10、协议
/*
协议中定义的要求自动接收协议的访问级别,不能单独设置访问级别
public协议定义的要求也是public
协议实现的访问级别必须 ≥ 类型的访问级别,或者 ≥ 协议的访问级别
下面代码能编译通过么?
 */

//public protocol ACCRunnable10 {
//    func run()
//}
//
//public class ACCPerson10 : ACCRunnable10 {
//    func run() {}
//}
//11、扩展
/*
如果有显式设置扩展的访问级别,扩展添加的成员自动接收扩展的访问级别
如果没有显式设置扩展的访问级别,扩展添加的成员的默认访问级别,跟直接在类型中定义的成员一样
可以单独给扩展添加的成员设置访问级别
不能给用于遵守协议的扩展显式设置扩展的访问级别


在同一文件中的扩展,可以写成类似多个部分的类型声明
在原本的声明中声明一个私有成员,可以在同一文件的扩展中访问它
在扩展中声明一个私有成员,可以在同一文件的其他扩展中、原本声明中访问它
 */

public class ACCPerson11 {
    private func run0() {}
    private func eat0() {
        run1()
    }
}

extension ACCPerson11 {
    private func run1() {}
    private func eat1() {
        run0()
    }
}

extension ACCPerson11 {
    private func eat2() {
        run1()
    }
}

将方法赋值给let/var

//二、将方法赋值给let/var
func fnSet() -> Void {
    //方法也可以像函数那样,赋值给一个let或者var
    struct Person {
        var age: Int = 0
        
        func run(_ v: Int) {
            print("func run", age, v,self)
        }
        
        static func run(_ v: Int) {
            print("static func run", v,self)
        }
    }
    
    let fn1 = Person.run
    fn1(10) // static func run 10 Person
    
    let fn2: (Int) -> () = Person.run
    fn2(20) // static func run 20 Person
    
    let fn3: (Person) -> ((Int) -> ()) = Person.run
    fn3(Person(age: 18))(30) // func run 18 30 Person(age: 18)
    
    let per = Person()
    let objfn = per.run
    objfn(40)// func run 0 40 Person(age: 0)
}

行者常至,为者常成!





R
Valine - A simple comment system based on Leancloud.