Latest web development tutorials

Swift access control

Access control can be defined in other source files or modules of code to your code access level.

You can explicitly to a single type (class, struct, enum) to set access levels, can also give these types of properties, functions, initialization method, the basic type, the subscript indexes set access levels.

Agreement may also be limited to use within a certain range, including the agreement in global constants, variables and functions.

Based access control module with the source files.

Modules are defined by a separate unit to build and publish Framework or Application. A module can be used in the Swift in the import keyword introduces another module.

The source file is a single source file, which usually belongs to a module that contains the source files can define multiple classes and functions.

Swift provides three different levels of access code entity: public, internal, private.

Access Level definition
Public Any entity that can access your files in the source module, others can access the source files of all entities through the introduction of the module.
Internal : Any entity that can access your files in the source module, but others can not access the source module file entities.
Private Use only entity in the current source file, known as a private entity.

public access to the most advanced level, private is the lowest level of access.

grammar

By declaring modifiers public, internal, private access level entities:

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

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

Unless there are special instructions, otherwise entities use the default access level internal.


Function Type Access

Access levels based on parameters derived function requires the type of the function's return type and level of access.

The following example defines a named someFunction global function, and does not explicitly affirm their access level.

func someFunction() -> (SomeInternalClass, SomePrivateClass) {
    // 函数实现
}

Function in one of the classes SomeInternalClass access level is internal, the other SomePrivateClass access level is private. Therefore, according to the principle of access level tuple, the tuple access level is private.

Because the function returns the type of the access level is private, so you must use the private modifier explicitly declare the function:
private func someFunction() -> (SomeInternalClass, SomePrivateClass) {
    // 函数实现
}

This function is declared as public or internal, or use the default internal access levels are wrong.


Access enumerated type

Access level enumeration members inherited from the enumeration, you can not enumerate the members of a separate declaration different levels of access.

Examples

For example, the following example, the enumeration Student is explicitly declared as public level, then its members Name, Mark's level of access is also 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("学生名: \(studName).")
case .Mark(let Mark1, let Mark2, let Mark3):
    print("学生成绩: \(Mark1),\(Mark2),\(Mark3)")
}

The above program execution output is:

学生成绩: 98,97,95

Subclasses access

Access level subclass shall not exceed the level of access of the parent class. For example, the access level of the parent class is internal, the access level of the subclass can not be declared as public.

public class SuperClass {
    private func show() {
        print("超类")
    }
}

// 访问级别不能低于超类 internal > public
internal class SubClass: SuperClass  {
    override internal func show() {
        print("子类")
    }
}

let sup = SuperClass()
sup.show()

let sub = SubClass()
sub.show()

The above program execution output is:

超类
子类

Constants, variables, properties, index access

Constants, variables, attributes can not have more than their type of access levels.

For example, you define a level of public property, but it is the type of private level, which is not allowed by the compiler.

Similarly, the index can not have a higher return than the index type or types of access levels.

If the constants, variables, properties, the subscript index defined type is private level, they must be clearly stated the level of access to private:

private var privateInstance = SomePrivateClass()

Getter and Setter access

Getters and Setters access level constants, variables, properties, subscript index inherited from the level of access they belong to members.

Setter access levels may be lower than the access level corresponding Getter, so you can control the variables, properties or subscript index read and write permissions.

class Samplepgm {
    private var counter: Int = 0{
        willSet(newTotal){
            print("计数器: \(newTotal)")
        }
        didSet{
            if counter > oldValue {
                print("新增加数量 \(counter - oldValue)")
            }
        }
    }
}

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

The above program execution output is:

计数器: 100
新增加数量 100
计数器: 800
新增加数量 700

Constructor and default constructor access

initialization

We can customize the initialization method to declare the level of access, but it belongs to the class or else higher level of access. But necessary constructor exception, it must access level and access to the same level of their class.

As a function or method parameters, method of access level initialization parameters can not be less than the access level initialization method.

The default initialization method

Swift is a structure, the class provides a default initialization method with no parameters, for all of their property to provide assignment, but does not give a specific value.

The default initialization method belongs to the same level of access and the type of access level.

Examples

Use the keyword statement required before access () init method in each subclass.

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

The above program execution output is:

10
30
10

Access Agreement

If you want a clear agreement affirms the access level, we need to note that you want to make sure the agreement is only used in the access level role you stated domain.

If you define a public access level protocol, to achieve the necessary function of the agreement it will be provided by the public access level. This is different from other types, such as other types of public access level, the level of access for members of their internal.

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 show = SubClass(no1: 30, no2: 50)

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

The above program execution output is:

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

Extended access

You can under the conditions allow the class, structure, enumeration expansion. Extended members of the original class members should have the same level of access. For example, you extend a common type, then you add the new members should have the same members of the original default internal access level.

Alternatively, you can explicitly declare the extended level of access (such as the use of private extension) within the extension to all members affirm a new default access level. The new default access level can still be affirmed individual member covered by the access level.


Generic Access

Access level generic type or generic functions to take the generic type, the function itself, the generic type parameter of the three lowest levels of access.

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

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

tos.push("泛型")
print(tos.items)

tos.push("类型参数")
print(tos.items)

tos.push("类型参数名")
print(tos.items)
let deletetos = tos.pop()

The above program execution output is:

["Swift"]
["Swift", "泛型"]
["Swift", "泛型", "类型参数"]
["Swift", "泛型", "类型参数", "类型参数名"]

Type alias

Anything you type aliases will be defined as a different type, in order to facilitate access control. Access level of a type alias type can not be higher than the original level of access.

For example, a private class type aliases can be assigned to a public, internal, private type, but a public level type aliases can only be set to a public level type can not be set to internal or private level type .

Note: This rule also applies to the case in order to meet protocol conformance to the relevant type name and an alias.

public protocol Container {
    typealias 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)
    }
    
    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("Swift")
print(tos.items)

tos.push("泛型")
print(tos.items)

tos.push("Where 语句")
print(tos.items)

var eos = ["Swift", "泛型", "Where 语句"]
print(eos)

The above program execution output is:

["Swift"]
["Swift", "泛型"]
["Swift", "泛型", "Where 语句"]
["Swift", "泛型", "Where 语句"]