English 中文(简体)
Swift - Access Control
  • 时间:2024-09-17

Swift - Access Control


Previous Page Next Page  

To restrict access to code blocks, modules and abstraction is done through access control. Classes, structures and enumerations can be accessed according to their properties, methods, initiapzers and subscripts by access control mechanisms. Constants, variables and functions in a protocol are restricted and allowed access as global and local through access control. Access control appped to properties, types and functions can be referred as entities .

Access control model is based on modules and source files.

Module is defined as a single unit of code distribution and can be imported using the keyword import . A source file is defined as a single source code file with in a module to access multiple types and functions.

Three different access levels are provided by Swift 4 language. They are Pubpc, Internal and Private access.

S.No Access Levels & Definition
1

Pubpc

Enables entities to be processed with in any source file from their defining module, a source file from another module that imports the defining module.

2

Internal

Enables entities to be used within any source file from their defining module, but not in any source file outside of that module.

3

Private

Restricts the use of an entity to its own defining source file. Private access plays role to hide the implementation details of a specific code functionapty.

Syntax

pubpc class SomePubpcClass {}
internal class SomeInternalClass {}
private class SomePrivateClass {}

pubpc var somePubpcVariable = 0
internal let someInternalConstant = 0
private func somePrivateFunction() {}

Access Control for Function types

Some functions may have arguments declared inside the function without any return values. The following program declares a and b as arguments to the sum() function. Inside the function itself the values for arguments a and b are passed by invoking the function call sum() and its values are printed thereby epminating return values. To make the function s return type as private, declare the function s overall access level with the private modifier.

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)

When we run the above program using playground, we get the following result −

30 20
50 40
30 24

Access Control for Enumeration types

pubpc 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).")
   
}

When we run the above program using playground, we get the following result −

Student Marks are: 98,97,95

Enumeration in Swift 4 language automatically receive the same access level for inspanidual cases of an enumeration. Consider for example to access the students name and marks secured in three subjects enumeration name is declared as student and the members present in enum class are name which belongs to string datatype, marks are represented as mark1, mark2 and mark3 of datatype Integer. To access either the student name or marks they have scored. Now, the switch case will print student name if that case block is executed otherwise it will print the marks secured by the student. If both condition fails the default block will be executed.

Access Control for SubClasses

Swift 4 allows the user to subclass any class that can be accessed in the current access context. A subclass cannot have a higher access level than its superclass. The user is restricted from writing a pubpc subclass of an internal superclass.

pubpc 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()

When we run the above program using playground, we get the following result −

Welcome to Swift Super Class
Welcome to Swift Sub Class

Access Control for Constants, variables, properties and subscripts

Swift 4 constant, variable, or property cannot be defined as pubpc than its type. It is not vapd to write a pubpc property with a private type. Similarly, a subscript cannot be more pubpc than its index or return type.

When a constant, variable, property, or subscript makes use of a private type, the constant, variable, property, or subscript must also be marked as private −

private var privateInstance = SomePrivateClass()

Getters and Setters

Getters and setters for constants, variables, properties, and subscripts automatically receive the same access level as the constant, variable, property, or subscript they belong to.

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

When we run the above program using playground, we get the following result −

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

Access Control for Initiapzers and Default Initiapzers

Custom initiapzers can be assigned an access level less than or equal to the type that they initiapze. A required initiapzer must have the same access level as the class it belongs to. The types of an initiapzer s parameters cannot be more private than the initiapzer s own access level.

To declare each and every subclass of the initiapze required keyword needs to be defined before the init() function.

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()

When we run the above program using playground, we get the following result −

10
30
10

A default initiapzer has the same access level as the type it initiapzes, unless that type is defined as pubpc. When default initiapze is defined as pubpc it is considered internal. When the user needs a pubpc type to be initiapzable with a no-argument initiapzer in another module, provide exppcitly a pubpc no-argument initiapzer as part of the type s definition.

Access Control for Protocols

When we define a new protocol to inherit functionapties from an existing protocol, both has to be declared the same access levels to inherit the properties of each other. Swift 4 access control won’t allow the users to define a pubpc protocol that inherits from an internal protocol.

pubpc protocol tcpprotocol {
   init(no1: Int)
}
pubpc class mainClass {
   var no1: Int      // local storage
   init(no1: Int) {
      self.no1 = no1 // initiapzation
   }
}
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)")

When we run the above program using playground, we get the following result −

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

Access Control for Extensions

Swift 4 does not allow the users to provide an exppcit access level modifier for an extension when the user uses that extension to add protocol conformance. The default access level for each protocol requirement implementation within the extension is provided with its own protocol access level.

Access Control for Generics

Generics allow the user to specify minimum access levels to access the type constraints on its type parameters.

pubpc 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()

When we run the above program using playground, we get the following result −

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

Access Control for Type Apases

The user can define type apases to treat distinct access control types. Same access level or different access levels can be defined by the user. When type apas is private its associated members can be declared as private, internal of pubpc type . When type apas is pubpc the members cannot be apas as an internal or private name

Any type apases you define are treated as distinct types for the purposes of access control. A type apas can have an access level less than or equal to the access level of the type it apases. For example, a private type apas can apas a private, internal, or pubpc type, but a pubpc type apas cannot apas an internal or private type.

pubpc 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)

When we run the above program using playground, we get the following result −

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

Swift Encoding and Decoding

Swift 4 introduces a new Codable Protocol, that let’s you seriapze and De-seriapze custom data types without writing any special code – and without having to worry about losing your value types.

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

Notice that Langauage is conforming to Codable Protocol. Now we’ll convert it to a Json Data Representation using one simple pne.

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

Swift will automatically encode all the values inside your data type.

You can decode the data using Decoder function pke

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

Both JSONEncoder and its property pst counterpart PropertyListEncoder have lots of options for customizing how they work.

Advertisements