Swift学习之访问限定

版权声明:不积跬步无以至千里,不积小流无以成江海! https://blog.csdn.net/Bolted_snail/article/details/87634878

Swift访问级别

  • Swift提供了5种访问级别,对应的访问修饰符为:open、public、internal、fileprivate、private。这些访问修饰符可以修饰类、结构体、枚举等面向对象的类型,还可以修饰变量、常量、下标、元组、函数、属性等内容。

  • 5种访问级别修饰符的区别

    1. open: 公开权限, 最高的权限, 可以被其他模块访问, 继承及复写。
    2. public: 公有访问权限,类或者类的公有属性或者公有方法可以从文件或者模块的任何地方进行访问。那么什么样才能称为一个模块呢?一个App就是一个模块,一个第三方API, 第三等方框架等都是一个完整的模块,这些模块如果要对外留有访问的属性或者方法,就应该使用public的访问权限。Swift 3.0以后在同意模块中和open一样可以被访问,在不同模块时,public所声明的类不能被继承,public声明的属性和方法不能被重写(override)
    3. internal: 顾名思义,internal是内部的意思,默认访问限定,即有着internal访问权限的属性和方法说明在模块内部可以访问,超出模块内部就不可被访问了。
    4. fileprivate: 文件私有访问权限,只有在当前源文件中被访问(.swift文件)
    5. private: 私有访问权限,只能在类型内部被访问
  • 示例,两个.swift源文件如下
    .swift源文件
    Test.swift文件中声明两个类Test和Test2,其中Test2是继承Test。

import Cocoa
internal class Test: NSObject {
    open var name1:String = "1"       //开放的,访问限制最小,无论自己模块内部,还是其他模块,都可以被访问
    public var name2:String = "2"    //公共的,在同意模块中和open一样可以被访问,在不同模块时,public所声明的类不能被继承,public声明的属性和方法不能被重写(override)
    internal var name3:String = "3"   //内部的,默认访问限定,internal实体只能在自己模块中被访问
    fileprivate var name4:String = "4" //文件私有的,只能在当前源文件中被访问
    private var name5:String?{    //私有的,只能在类内部被访问
        return"5"
    }
    
     func test(){
        print(name5!)
    }
    
    class Test3:Test{
        
    }
}

class Test2: Test {
   override  func test(){
    print(self.name1)
    print(self.name2)
    print(self.name3)
    print(self.name4)
//    print(name5!) 不能访问
    }
}

main.swift中主要是去访问Test、Test2的属性和方法。

import Foundation
let t = Test()
print(t.name1)
print(t.name2)
print(t.name3)
//print(t.name4)
//print(t.name5)
print("--------")
t.test()
print("--------")
let t2 = Test2()
print(t2.name1)
print(t2.name2)
print(t2.name3)
print("--------")
t2.test()

打印结果
Testprivate修饰的属性name5,只能在Test类中可以访问,在Test2中不能访问(虽然Test,Test2在同一个.swift源文件中),但是fileprivate修饰的name4是可以在Test2中访问,但是不能再main.swift文件中被访问。其他因为都在同一个模块,可以被访问。

Swift访问限定原则

  • 由于Swift中访问限制符能够修饰的实体很多,使用起来比较繁琐,所以我们总结几个实用原则。

1.统一性原则

  • 原则1:如果一个类型(类、结构体、枚举)定义我internal或private,那么类型声明的变量或常量不能使用public访问级别。因为public的变量或常量可以被任何人访问,而internal或private的类型不可以。
private class Employee{
    var no = ""
    var name = ""
}
internal struct Department{
    var no = ""
    var name = ""
}

let emp = Employee() //编译报错,私有的类智能在类内部可以访问
public let dep = Department() //编译报错
  • 原则2:函数的访问级别不能高于他的参数和返回值类型的访问级别。假设函数声明为public级别,而参数或返回值类型为internal或private,就会出现函数可以被任何人访问,而他的参数或返回值类型不可以访问的矛盾情况。
 class Employee{
    var no = ""
    var name = ""
    var dept: Department?
    
}
 struct Department{
    var no = ""
    var name = ""
}

public func getEmpDept(emp:Employee)-> Department?{ //编译报错
    return emp.dept
}

在这里插入图片描述
getEmpDept函数中的参数访问级别是internal与函数访问级别public不一致。

public class Employee{
    var no = ""
    var name = ""
    var dept: Department?
    
}
 struct Department{
    var no = ""
    var name = ""
}

public func getEmpDept(emp:Employee)-> Department?{
    return emp.dept
}

在这里插入图片描述
如果将Employee改成public依然会报返回值类型与函数不一致的错误。

2.设计原则

  • 如果我们编写的是应用程序,应用程序包中的所有Swift文件和其中定义的实体都是供本应用使用的,而不是提供其他模块使用的那么我们就不用设置访问级别了,既使用默认的访问级别internal。
  • 如果我们开发的是框架,框架编译的文件不能独立运行,因此就是给别人使用的,这种情况下要详细设计其中的Swift文件和实体的访问级别,让别人使用的可以设定为public,不想让别人看到的可以设定为internal或private。

3.元组类型访问级别

  • 元组类型的访问界别,遵循元组中字段最低的访问级别。
private class Employee{
    var no = ""
    var name = ""
    var dept: Department?
    
}
struct Department{
    var no = ""
    var name = ""
}
private let emp = Employee()
var dept = Department()
private var person = (emp,dept)

在这里插入图片描述
如果person前面不加private就会报错,类型不匹配,必须用private修饰。

4.枚举类型访问级别

  • 枚举中成员的访问级别继承自该枚举,因此我们不能为枚举中的成员指定访问级别。
public enum WeekDays {
    case Monday
    case Tuesday
    case Wednesday
    case Thursday
    case Friday
}

由于WeekDays枚举类型是public访问级别,因而他的成员也是bublic访问级别的。

猜你喜欢

转载自blog.csdn.net/Bolted_snail/article/details/87634878