Swift - Control de acceso

Para restringir el acceso a bloques de código, módulos y abstracción se realiza a través del control de acceso. Se puede acceder a clases, estructuras y enumeraciones según sus propiedades, métodos, inicializadores y subíndices mediante mecanismos de control de acceso. Las constantes, variables y funciones en un protocolo están restringidas y se permite el acceso como global y local a través del control de acceso. El control de acceso aplicado a propiedades, tipos y funciones puede denominarse "entidades".

El modelo de control de acceso se basa en módulos y archivos fuente.

El módulo se define como una sola unidad de distribución de código y se puede importar utilizando la palabra clave 'importar'. Un archivo fuente se define como un archivo de código fuente único dentro de un módulo para acceder a múltiples tipos y funciones.

Swift 4 language proporciona tres niveles de acceso diferentes. Son de acceso Público, Interno y Privado.

S. No Niveles de acceso y definición
1

Public

Permite que las entidades se procesen en cualquier archivo fuente de su módulo de definición, un archivo fuente de otro módulo que importa el módulo de definición.

2

Internal

Permite que las entidades se utilicen dentro de cualquier archivo fuente desde su módulo de definición, pero no en ningún archivo fuente fuera de ese módulo.

3

Private

Restringe el uso de una entidad a su propio archivo fuente de definición. El acceso privado juega un papel importante para ocultar los detalles de implementación de una funcionalidad de código específico.

Sintaxis

public class SomePublicClass {}
internal class SomeInternalClass {}
private class SomePrivateClass {}

public var somePublicVariable = 0
internal let someInternalConstant = 0
private func somePrivateFunction() {}

Control de acceso para tipos de funciones

Algunas funciones pueden tener argumentos declarados dentro de la función sin ningún valor de retorno. El siguiente programa declara ayb como argumentos de la función sum (). Dentro de la función en sí, los valores para los argumentos ayb se pasan invocando la llamada a la función sum () y sus valores se imprimen eliminando así los valores de retorno. Para que el tipo de retorno de la función sea privado, declare el nivel de acceso general de la función con el modificador privado.

private func sum(a: Int, b: Int) {
   let a = a + b
   let b = a - b
   print(a, b)
}

sum(a: 20, b: 10)
sum(a: 40, b: 10)
sum(a: 24, b: 6)

Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:

30 20
50 40
30 24

Control de acceso para tipos de enumeración

public enum Student {
   case Name(String)
   case Mark(Int,Int,Int)
}
var studDetails = Student.Name("Swift 4")
var studMarks = Student.Mark(98,97,95)

switch studMarks {
   case .Name(let studName):
      print("Student name is: \(studName).")
   case .Mark(let Mark1, let Mark2, let Mark3):
      print("Student Marks are: \(Mark1),\(Mark2),\(Mark3).")
   
}

Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:

Student Marks are: 98,97,95

La enumeración en el idioma Swift 4 recibe automáticamente el mismo nivel de acceso para casos individuales de una enumeración. Considere, por ejemplo, acceder al nombre de los estudiantes y las marcas aseguradas en tres materias, el nombre de la enumeración se declara como estudiante y los miembros presentes en la clase de enumeración son nombres que pertenecen al tipo de datos de cadena, las marcas se representan como mark1, mark2 y mark3 del tipo de datos Integer. Para acceder al nombre del estudiante o las notas que ha obtenido. Ahora, el caso del interruptor imprimirá el nombre del estudiante si ese bloque de caso se ejecuta, de lo contrario, imprimirá las marcas aseguradas por el estudiante. Si ambas condiciones fallan, se ejecutará el bloque predeterminado.

Control de acceso para subclases

Swift 4 permite al usuario subclasificar cualquier clase a la que se pueda acceder en el contexto de acceso actual. Una subclase no puede tener un nivel de acceso más alto que su superclase. El usuario no puede escribir una subclase pública de una superclase interna.

public class cricket {
   internal func printIt() {
      print("Welcome to Swift 4 Super Class")
   }
}

internal class tennis: cricket {
   override internal func printIt() {
      print("Welcome to Swift 4 Sub Class")
   }
}

let cricinstance = cricket()
cricinstance.printIt()

let tennisinstance = tennis()
tennisinstance.printIt()

Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:

Welcome to Swift Super Class
Welcome to Swift Sub Class

Control de acceso para constantes, variables, propiedades y subíndices

La constante, variable o propiedad de Swift 4 no se puede definir como pública más que su tipo. No es válido escribir una propiedad pública con un tipo privado. De manera similar, un subíndice no puede ser más público que su índice o tipo de retorno.

Cuando una constante, variable, propiedad o subíndice hace uso de un tipo privado, la constante, variable, propiedad o subíndice también debe marcarse como privado:

private var privateInstance = SomePrivateClass()

Getters y Setters

Los captadores y definidores de constantes, variables, propiedades y subíndices reciben automáticamente el mismo nivel de acceso que la constante, variable, propiedad o subíndice al que pertenecen.

class Samplepgm {
   var counter: Int = 0{
      willSet(newTotal) {
         print("Total Counter is: \(newTotal)")
      }
      didSet {
         if counter > oldValue {
            print("Newly Added Counter \(counter - oldValue)")
         }
      }
   }
}

let NewCounter = Samplepgm()
NewCounter.counter = 100
NewCounter.counter = 800

Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:

Total Counter is: 100
Newly Added Counter 100
Total Counter is: 800
Newly Added Counter 700

Control de acceso para inicializadores e inicializadores predeterminados

A los inicializadores personalizados se les puede asignar un nivel de acceso menor o igual al tipo que inicializan. Un inicializador obligatorio debe tener el mismo nivel de acceso que la clase a la que pertenece. Los tipos de parámetros de un inicializador no pueden ser más privados que el propio nivel de acceso del inicializador.

Para declarar todas y cada una de las subclases de la palabra clave initialize 'required' debe definirse antes de la función init ().

class classA {
   required init() {
      let a = 10
      print(a)
   }
}
class classB: classA {
   required init() {
      let b = 30
      print(b)
   }
}
let res = classA()
let print = classB()

Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:

10
30
10

Un inicializador predeterminado tiene el mismo nivel de acceso que el tipo que inicializa, a menos que ese tipo esté definido como público. Cuando la inicialización predeterminada se define como pública, se considera interna. Cuando el usuario necesita que un tipo público se pueda inicializar con un inicializador sin argumentos en otro módulo, proporcione explícitamente un inicializador público sin argumentos como parte de la definición del tipo.

Control de acceso para protocolos

Cuando definimos un nuevo protocolo para heredar funcionalidades de un protocolo existente, ambos deben declararse con los mismos niveles de acceso para heredar las propiedades del otro. El control de acceso de Swift 4 no permitirá a los usuarios definir un protocolo "público" que herede de un protocolo "interno".

public protocol tcpprotocol {
   init(no1: Int)
}
public class mainClass {
   var no1: Int      // local storage
   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)
   }
   
   // Requires only one parameter for convenient method
   required override convenience init(no1: Int) {
      self.init(no1:no1, no2:0)
   }
}

let res = mainClass(no1: 20)
let print = subClass(no1: 30, no2: 50)

print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")

Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:

res is: 20
res is: 30
res is: 50

Control de acceso para extensiones

Swift 4 no permite a los usuarios proporcionar un modificador de nivel de acceso explícito para una extensión cuando el usuario usa esa extensión para agregar conformidad con el protocolo. El nivel de acceso predeterminado para cada implementación de requisitos de protocolo dentro de la extensión se proporciona con su propio nivel de acceso de protocolo.

Control de acceso para genéricos

Los genéricos permiten al usuario especificar niveles mínimos de acceso para acceder a las restricciones de tipo en sus parámetros de tipo.

public struct TOS<T> {
   var items = [T]()
   mutating func push(item: T) {
      items.append(item)
   }
   mutating func pop() -> T {
      return items.removeLast()
   }
}

var tos = TOS<String>()
tos.push(item: "Swift 4")
print(tos.items)

tos.push(item: "Generics")
print(tos.items)

tos.push(item: "Type Parameters")
print(tos.items)

tos.push(item: "Naming Type Parameters")
print(tos.items)
let deletetos = tos.pop()

Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:

[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Type Parameters]
[Swift 4, Generics, Type Parameters, Naming Type Parameters]

Control de acceso para alias de tipo

El usuario puede definir alias de tipo para tratar distintos tipos de control de acceso. El usuario puede definir el mismo nivel de acceso o diferentes niveles de acceso. Cuando el alias de tipo es 'privado', sus miembros asociados pueden declararse como 'privados, internos de tipo público'. Cuando el tipo de alias es público, los miembros no pueden ser alias como un nombre 'interno' o 'privado'

Los alias de tipo que defina se tratan como tipos distintos a los efectos del control de acceso. Un alias de tipo puede tener un nivel de acceso menor o igual que el nivel de acceso del tipo al que se alias. Por ejemplo, un alias de tipo privado puede alias un tipo privado, interno o público, pero un alias de tipo público no puede alias un tipo interno o privado.

public protocol Container {
   associatedtype ItemType
   mutating func append(item: ItemType)
   var count: Int { get }
   subscript(i: Int) -> ItemType { get }
}
struct Stack<T>: Container {
   // original Stack<T> implementation
   var items = [T]()
   mutating func push(item: T) {
      items.append(item)
   }
   mutating func pop() -> T {
      return items.removeLast()
   }
   
   // conformance to the Container protocol
   mutating func append(item: T) {
      self.push(item: item)
   }
   var count: Int {
      return items.count
   }
   subscript(i: Int) -> T {
      return items[i]
   }
}
func allItemsMatch<
   C1: Container, C2: Container
   where C1.ItemType == C2.ItemType, C1.ItemType: Equatable>
   (someContainer: C1, anotherContainer: C2) -> Bool {
   
   // check that both containers contain the same number of items
   if someContainer.count != anotherContainer.count {
      return false
   }
   
   // check each pair of items to see if they are equivalent
   for i in 0..<someContainer.count {
      if someContainer[i] != anotherContainer[i] {
         return false
      }
   }
   // all items match, so return true
   return true
}
var tos = Stack<String>()
tos.push(item: "Swift 4")
print(tos.items)

tos.push(item: "Generics")
print(tos.items)

tos.push(item: "Where Clause")
print(tos.items)

var eos = ["Swift 4", "Generics", "Where Clause"]
print(eos)

Cuando ejecutamos el programa anterior usando el patio de recreo, obtenemos el siguiente resultado:

[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Where Clause]
[Swift 4, Generics, Where Clause]

Codificación y decodificación rápida

Swift 4 presenta un nuevo Codable Protocolo, que le permite serializar y deserializar tipos de datos personalizados sin escribir ningún código especial y sin tener que preocuparse por perder sus tipos de valor.

struct Language: Codable {
   var name: String
   var version: Int
}
let swift = Language(name: "Swift", version: 4)
let java = Language(name: "java", version: 8)
let R = Language(name: "R", version: 3

Tenga en cuenta que Langauage se ajusta al Protocolo de codificación. Ahora lo convertiremos a una representación de datos Json usando una línea simple.

let encoder = JSONEncoder()
if let encoded = try? encoder.encode(java) {
   //Perform some operations on this value.
}

Swift codificará automáticamente todos los valores dentro de su tipo de datos.

Puede decodificar los datos utilizando la función Decodificador como

let decoder = JSONDecoder()
if let decoded = try? decoder.decode(Language.self, from: encoded) {
   //Perform some operations on this value.
}

Tanto JSONEncoder como su contraparte de lista de propiedades PropertyListEncoder tienen muchas opciones para personalizar su funcionamiento.