Swift学习笔记

Swift - 访问控制

2022-04-24  本文已影响0人  aven_kang

Open>Public>Internal>Fileprivate>private

1.Open

允许在定义实体的模块、其他模块中访问,允许其他模块进行继承、重写(open只能用在类、类成员上)PS:模块,其实指的是差不多是整个项目的工程,基本都能访问Open定义的类

2.Public

允许在定义实体的模块、其他模块中访问,不允许其他模块进行继承、重写

3.internal

只允许在定义实体的模块中访问,不允许在他模块中访问,比如一些动态库

4.fileprivate

只允许在定义实体的源文件中访问,比如,在main文件中定义了一个这样的函数,那么这个函数就只能在main文件中使用
fileprivate class test {
}

5.private

只允许在定义实体的封闭声明中访问,下面的代码中,age 被定义了private,那么age只能在Person这个类中使用
fileprivate class Person {
    private var age: Int
}
如果没有任何访问限定,那么大部分默认的都是internal级别

访问级别的使用准则

一个实体不可以被更低访问级别的实体定义

1.参数类型、返回值类型 >= 函数
internal func test(_  num: Int) -> Double {
    return 0.0
}

num的访问级别,要比test这个函数要高

2.父类>=子类
截屏2022-03-03 下午1.31.33.png
3.父协议>=子协议

同理可推

4.原类型 >= typealias
截屏2022-03-03 下午1.52.14.png

上图中可以看出,Aimal默认是internal级别的,而定义Myanimal时,使用的是pubulic级别,而public>internal的,所以是不允许的

5.原始值类型、关联值类型 >= 枚举类型
截屏2022-03-03 下午1.58.57.png
fileprivate typealias MyInt = Int
fileprivate typealias MyString = String

fileprivate enum Score {
    case point(MyInt)
    case grade(MyString)
}
6.定义类型A时用到其他类型>= 类型A
7.变量类型的访问级别 >= 变量的访问级别
fileprivate class Person {}

internal var person:Person

在上面的代码中,可以看到,Person类的级别是fileprivate,而声明的Person变量却是internal,级别是比fileprivate高的,这是不允许的,因为Person类只允许在当前的文件中使用,而internal是实体的模块都可以使用,这是矛盾的

元组类型的访问级别

internal struct Dog {}
fileprivate class Person {}

// (Dog,Person)的访问级别(最低)是fileprivate
fileprivate var data1: (Dog,Person) 
private var data2:(Dog,Person)

总结来讲,右边的级别,要比左边的大或者相等

泛型类型的访问级别

internal class Car {}
fileprivate class Dog {}
public class Person<T1,T2>{}

fileprivate var p = Person<Car,Dog>()

从这一句来看Person<Car,Dog>(),Person,Car,Dog三个对象,我们要挑选出级别最低的,最低的是fileprivate,而声明p这个对象的时候,他的级别是fileprivate,是等同的,所以是允许的。

成员、嵌套类型

类型的访问级别会影响成员(属性、方法、初始化器、下标)、嵌套类型的默认访问级别
1.一般情况下,类型为private、fileprivate,那么成员、嵌套类型默认也是private或者fileprivate
2.一般情况下,类型为internal、public,那么成员或者嵌套类型默认也是internal

初始化器

如果一个public类想在另一个模块调用编译生成的默认无参初始化器,必须显示提供public的无参初始化器,因为public类的默认初始化器是internal级别的,这个级别是不允许动态库访问的
public class test {
      public init(){
   }
}
如果结构体有private、fileprivate的存储实例属性,那么它的成员初始化器也是private、fileprivate,否则默认就是internal
struc Point {
   fileprivate var x = 0
   var y = 10
}
var p = Poin(x:10,y:10)

上述代码中,因为Point的x是赋值为fileprivate,所以Point(x:10,y:10)这个初始化出来的结构体,级别也是fileprivate

协议的访问级别

protocol Runnable {
    private func run() // 这样写会报错
}

所以要这样写

private protocol Runnable {
    func run() // 这样写会报错
}
截屏2022-03-03 下午3.00.05.png

从上图,我们可以看到,students是public级别的,而students里面默认的将会是internal级别,而test方法在协议中是public级别的,在students将会变成默认internal级别,所以会报错,这就需要在test方法前面加个pulic,提高级别,才不会报错,如下代码

public protocol Runnable {
//    func test() -> Self
//    init()
    func test()
    
}

public class students : Runnable {
    
   
    public func test() {
        
    }
    
}

扩展 - 把函数赋值给let,var

struct Panda {
    var age:Int
    func run(_ v:Int) {print("aa")}
//    static func run(_ v:Int) {
//        print("aa")
//    }
}

var fn = Panda.run // 此时的fn = (Panda)->((Int) -> ())
var fn2 = fn(Panda(age: 10))
fn2(20) // 这才是真正的调用run方法
``


上一篇下一篇

猜你喜欢

热点阅读