English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Access control can limit the access level of code in other source files or modules to your code.
You can explicitly set the access level for a single type (class, structure, enumeration), as well as for properties, functions, initialization methods, basic types, and indexers of these types.
Protocols can also be limited to a certain range of use, including global constants, variables, and functions within the protocol.
Access control is based on modules and source files.
A module refers to a Framework or Application built and released as an independent unit. In Swift, a module can use the import keyword to import another module.
A source file is a single source code file, which usually belongs to a module. A source file can contain multiple class and function definitions.
Swift provides four different access levels for entities in code: public, internal, fileprivate, and private.
Access level | Definition |
---|---|
public | Can access any entity in the source files of its own module, and others can also access all entities in the source files by importing the module. |
internal | Can access any entity in the source files of its own module, but others cannot access the entities in the source files of the module. |
fileprivate | Private within the file, can only be used in the current source file. |
private | Only accessible within the class, and cannot be accessed outside the scope of the class or structure. |
public é o nível de acesso mais alto, e private é o nível de acesso mais baixo.
Declare o nível de acesso da entidade usando modificador public, internal, fileprivate, private:
public class SomePublicClass {} internal class SomeInternalClass {} fileprivate class SomeFilePrivateClass {} private class SomePrivateClass {} public var somePublicVariable = 0 internal let someInternalConstant = 0 fileprivate func someFilePrivateFunction() {} private func somePrivateFunction() {}
A menos que haja uma especificação especial, todas as entidades usam o nível de acesso padrão internal.
class SomeInternalClass {} // Nível de acesso internal let someInternalConstant = 0 // Nível de acesso internal
O nível de acesso da função deve ser determinado com base no nível de acesso do tipo do parâmetro e do tipo de retorno da função.
O exemplo a seguir define uma função global chamada someFunction e não declara explicitamente seu nível de acesso.
func someFunction() -> (SomeInternalClass, SomePrivateClass) { // Implementação da função {}
Um dos tipos da classe SomeInternalClass dentro da função tem nível de acesso internal, e o outro SomePrivateClass tem nível de acesso private. Portanto, de acordo com o princípio de nível de acesso do tupla, o nível de acesso do tupla é private (o nível de acesso do tupla é o mesmo que o tipo com nível de acesso mais baixo dentro do tupla).
Como o nível de acesso do tipo de retorno da função é private, você deve usar o modificador private para declarar explicitamente a função:
private func someFunction() -> (SomeInternalClass, SomePrivateClass) { // Implementação da função {}
É errado declarar a função como public ou internal, ou usar o nível de acesso padrão internal, porque assim você não poderá acessar o valor de retorno de nível private.
O nível de acesso dos membros do enum herda do enum, você não pode declarar níveis de acesso diferentes para membros do enum.
Por exemplo, no seguinte exemplo, o enum Student é explicitamente declarado como nível public, então o nível de acesso dos membros Name, Mark também é public:
public enum Student { case .Name(String) case .Mark(Int,Int,Int) {} var studDetails = Student.Name("Swift") var studMarks = Student.Mark(98,97,95) switch studMarks { case .Name(let studName): print("Nome do aluno: (studName).") case .Mark(let Mark1, let Mark2, let Mark3): print("Notas dos alunos: (Mark1),(Mark2),(Mark3)") {}
O resultado de execução do programa acima é:
Notas dos alunos: 98,97,95
O nível de acesso da subclasse não pode ser superior ao do pai. Por exemplo, se o nível de acesso do pai for internal, o nível de acesso da subclasse não pode ser declarado como public.
public class SuperClass { fileprivate func show() { print("Superclasse") {} {} // O nível de acesso não pode ser superior ao da superclasse internal > public internal class SubClass: SuperClass { override internal func show() { print("Subclasse") {} {} let sup = SuperClass() sup.show() let sub = SubClass() sub.show()
O resultado de execução do programa acima é:
Superclasse Subclasse
Constantes, variáveis e propriedades não podem ter um nível de acesso superior ao de seus tipos.
Por exemplo, se você definir uma propriedade de nível public, mas seu tipo for de nível private, isso não é permitido pelo compilador.
Da mesma forma, o índice não pode ter um nível de acesso superior ao do tipo de índice ou ao tipo de retorno.
Se o tipo de definição de constante, variável, propriedade, índice de subscrito for de nível private, então elas devem declarar explicitamente o nível de acesso como private:
private var privateInstance = SomePrivateClass()
Os níveis de acesso dos getters e setters de constantes, variáveis, propriedades e índices de subscrito herdam o nível de acesso dos membros aos quais pertencem.
O nível de acesso do setter pode ser inferior ao nível de acesso do getter correspondente, permitindo assim controlar as permissões de leitura e escrita de variáveis, propriedades ou índices de subscrito.
class Samplepgm { fileprivate var counter: Int = 0{ willSet(newTotal){ print("Contador: \(newTotal)") {} didSet{ if counter > oldValue { print("Quantidade adicionada (counter - oldValue") {} {} {} {} let NewCounter = Samplepgm() NewCounter.counter = 100 NewCounter.counter = 800
O nível de acesso do counter é fileprivate, acessível dentro do arquivo.
O resultado de execução do programa acima é:
Contador: 100 Quantidade adicionada 100 Contador: 800 Quantidade adicionada 700
Podemos declarar um nível de acesso para o método de inicialização personalizado, mas não pode ser superior ao nível de acesso da classe a que pertence. Exceto para o construtor necessário, cujo nível de acesso deve ser o mesmo que o nível de acesso da classe.
Como os parâmetros de função ou método, o nível de acesso dos parâmetros do método de inicialização não pode ser inferior ao nível de acesso do método de inicialização.
O Swift fornece um método de inicialização padrão sem parâmetros para estruturas e classes, usado para fornecer operações de atribuição para todas as propriedades, mas não fornece valores específicos.
O nível de acesso do método de inicialização padrão é o mesmo que o nível de acesso do tipo ao qual pertence.
Use a palavra-chave required antes do método init() de cada subclasse para declarar o nível de acesso.
class classA { required init() { var a = 10 print(a) {} {} class classB: classA { required init() { var b = 30 print(b) {} {} let res = classA() let show = classB()
O resultado de execução do programa acima é:
10 30 10
Se você quiser declarar explicitamente o nível de acesso de um protocolo, note que você deve garantir que o protocolo seja usado apenas no escopo de nível de acesso declarado.
Se você definiu um nível de acesso public para um protocolo, então as funções necessárias fornecidas pelo protocolo também serão de nível de acesso public. Isso é diferente de outros tipos, por exemplo, outros tipos de nível de acesso public, seus membros têm nível de acesso internal.
public protocol TcpProtocol {}} init(no1: Int) {} public class MainClass { var no1: Int // storage local init(no1: Int) { self.no1 = no1 // initialization {} {} class SubClass: MainClass, TcpProtocol { var no2: Int init(no1: Int, no2 : Int) { self.no2 = no2 super.init(no1:no1) {} // Requer apenas um parâmetro para o método conveniente Required only one parameter for convenient method1: Int) { self.init(no1:no1, no2:0) {} {} let res = MainClass(no1: 20) let show = SubClass(no1: 30, no2: 50) print("res is: \(res.no"1)") print("res is: \(show.no"1)") print("res is: \(show.no"2)")
O resultado de execução do programa acima é:
res is: 20 res is: 30 res is: 50
Você pode estender classes, estruturas e enums sob condições permitidas. Os membros da extensão devem ter o mesmo nível de acesso que os membros originais. Por exemplo, se você estender um tipo público, os novos membros devem ter o mesmo nível de acesso padrão internal que os membros originais.
Ou, você pode explicitamente declarar o nível de acesso da extensão (por exemplo, usando private extension) para todos os membros da extensão declarar um novo nível de acesso padrão. Este novo nível de acesso padrão ainda pode ser coberto por níveis de acesso declarados individualmente por membros.
O nível de acesso de um tipo genérico ou função genérica é o mais baixo entre o tipo genérico, a função em si e os parâmetros de tipo genérico.
public struct TOS<T> { var items = [T]() private mutating func push(item: T) { items.append(item) {} mutável func pop() -> T { return items.removeLast() {} {} var tos = TOS<String>() tos.push("Swift") print(tos.items) tos.push("Generics") print(tos.items) tos.push("Parâmetros de Tipo") print(tos.items) tos.push("Nome do Parâmetro de Tipo") print(tos.items) let deletetos = tos.pop()
O resultado de execução do programa acima é:
["Swift"] ["Swift", "Generics"] ["Swift", "Generics", "Parâmetros de Tipo"] ["Swift", "Generics", "Parâmetros de Tipo", "Nome do Parâmetro de Tipo"]
Qualquer tipo alias definido será tratado como um tipo diferente, facilitando o controle de acesso. O nível de acesso de um tipo alias não pode ser superior ao nível de acesso do tipo original.
por exemplo, um alias de tipo de nível private pode ser atribuído a um tipo public, internal ou private, mas um alias de tipo public pode ser atribuído apenas a um tipo public, não a um tipo internal ou private.
atenção: esta regra também se aplica a situações onde se nomeia um alias de tipo relacionado para atender a consistência do protocolo.
public protocol Container { typealias ItemType mutável func append(item: ItemType) var count: Int { get } subscrito(i: Int) -> ItemType { get } {} struct Stack<T>: Container { // implementação original Stack<T> var items = [T]() mutável func push(item: T) { items.append(item) {} mutável func pop() -> T { return items.removeLast() {} // conformidade com o protocolo Container mutável func append(item: T) { self.push(item) {} var count: Int { return items.count {} subscrito(i: Int) -> T { return items[i] {} {} func allItemsMatch< C1: Container, C2: Container onde C1.ItemType == C2.ItemType, C1.ItemType: Equatable> (someContainer: C1, anotherContainer: C2) -> Bool { // verifique se ambos os contêineres contêm o mesmo número de itens se someContainer.count != anotherContainer.count { return false {} // verifique cada par de itens para ver se eles são equivalentes for i in 0..<someContainer.count { if someContainer[i] != anotherContainer[i] { return false {} {} // Todos os itens coincidem, então retorne true return true {} var tos = Stack<String>() tos.push("Swift") print(tos.items) tos.push("Generics") print(tos.items) tos.push("Where Statement") print(tos.items) var eos = ["Swift", "Generics", "Where Statement"] print(eos)
O resultado de execução do programa acima é:
["Swift"] ["Swift", "Generics"] ["Swift", "Generics", "Where Statement"] ["Swift", "Generics", "Where Statement"]