Xiaoma Ge's Swift technology learning (day07--access control)

1. Access control

1. In terms of access permission control, Swift provides 5 different access levels (the following are arranged from high to low, the entity refers to the content modified by the access level)

1) open: allows access in the module that defines the entity and other modules (other modules refer to libraries or other targets), allowing other modules to inherit and rewrite (open can only be used on classes and class members)

2) Public: Allows access in the module that defines the entity and other modules, and does not allow other modules to inherit and rewrite.

3) internal: only allowed to be accessed in the module that defines the entity, not allowed to be accessed in other modules

4) fileprivate: only allowed to be accessed in the source file in which the entity is defined

5) private: only allowed to be accessed in the enclosing declaration that defines the entity

2. Most entities are internal level by default.

2. Rules for using access levels

1. An entity cannot be defined by entities with lower access levels, such as:

1) Variable/constant type >= variable/constant

The following example is wrong

//fileprivate class Person {
//
//}
//
//internal var person: Person

2) Parameter type, return value type >= function

func test(_ a: Int, _ b: Double) -> Double {
    return 10.0
}

Int and Double types are public-modified, and the test function is internal-modified, so it is correct

3) Parent class >= subclass

public class Person {

}

class Student: Person {

}

4) Original type >= typealias

class Person {  
}

fileprivate typealias MJPerson = Person

fileprivate typealias MyInt = Int
fileprivate typealias MyString = String
public enum Score {
   case point(MyInt)
   case grade(MyString)
}

5) Parent Agreement>= Child Agreement

6) Primitive value type, associated value type >= enumeration type

7) Other types used when defining type A >= type A

3. Tuple type

1. The access level of the tuple type is the lowest of all member types

internal struct Dog {}
fileprivate class Person {}
// (Dog,Person)的访问级别是fileprivate
fileprivate var data1: (Dog, Person)
private var data2: (Dog, Person)

4. Generic types

1. The access level of a generic type is the access level of types and of all generic types The lowest access level of the parameter

internal class Car {}
fileprivate class Dog {}
public class Person<T1, T2> {}
// Person<Car, Dog>的访问级别是fileprivate
fileprivate var p = Person<Car, Dog>()

​​​​

5. Members, nested types

1. The access level of a type will affect the default access level of members (properties, methods, initializers, subscripts) and nested types.

1) Generally, if the type is private or fileprivate, then the member and nested types will also be private or fileprivate by default.

2) Generally, if the type is internal or public, then the member and nested types default to internal.

public class PublicClass { // public
    public var p1 = 0 // public
    var p2 = 0 // internal
    fileprivate func f1() { } // fileprivate
    private func f2() { } // private
}

class InternalClass { // internal
    var p = 0 // internal
    fileprivate func f1() { } // fileprivate
    private func f2() { } //private
}

fileprivate class FilePrivateClass { // fileprivate
    func f1() { } // fileprivate
    private func f2() { } // private
}

private class PrivateClass { // private
    func f() { } // private
}

6. Rewriting of members

1. The access level of the overridden member of the subclass must be >= the access level of the subclass, or the access level of the overridden member of the subclass

public class Person5 {
    private var age: Int = 0
    public class Student5 : Person5 {
        override var age: Int {
            set {}
            get {10}
        }
    }
}

This code compiles correctly. The scope of age is in Person5.

2. Members of the parent class cannot be overridden by subclasses defined outside the member scope.

public class Person2 {
    private var age: Int = 0
}

public class Student2: Person2 {
    override var age: Int {
        set { }
        get { 10 }
    }
}

age is only valid in the scope of Person2

7. Can the following code be compiled and passed?

1. The first piece of code

private class Person {}
fileprivate class Student: Person{}

It can be compiled and passed because this is defined globally and the access level of Person is also this file.

2. Second generation code

private struct Dog {
    var age: Int = 0
    func run() { }
}

fileprivate struct Person {
    var dog: Dog = Dog()
    mutating func walk() {
        dog.run()
        dog.age = 1
    }
}

It can be compiled and passed. Dog is defined globally and is valid in the entire file, which is equivalent to fileprivate. Then its members age and run methods are actually equivalent to fileprivate modifications.

3. The third piece of code

private struct Dog {
   private var age: Int = 0
   private func run() { }
}

fileprivate struct Person {
    var dog: Dog = Dog()
    mutating func walk() {
        dog.run()
        dog.age = 1
    }
}

Compared with the second piece of code, this one explicitly declares the age and run methods as private, so the scope of age and run is only in the Dog class, so a compilation error occurs.

4. The fourth piece of code

class Test {
    private struct Dog {
        var age: Int = 0
        func run() {}
    }
    
    private struct Person {
        var dog: Dog = Dog()
        mutating func walk() {
            dog.run()
            dog.age = 1
        }
    }
}

It can be compiled and passed. The scope of Dog is in the Test function, so the scope of its members age and run methods are also in Test and can be accessed in Person.

5. The fifth piece of code

class Test {
    private struct Dog {
       private var age: Int = 0
       private func run() {}
    }
    
    private struct Person {
        var dog: Dog = Dog()
        mutating func walk() {
            dog.run()
            dog.age = 1
        }
    }
}

Report an error, age and fun can only be accessed in Dog

八、getter、setter

1. Getters and setters automatically receive the access level of the environment to which they belong by default.

2. You can set a separate access level for the setter that is lower than the getter to limit write permissions.

3. Stored properties also have getters and setters, but you cannot write { set{ }, get{ } }

class Person6 {
    private(set) var age = 0
    fileprivate(set) public var weight: Int {
        set {}
        get { 10 }
    }
    
   internal(set) public subscript(index: Int) -> Int {
        set { }
        get { index }
    }
}

9. Initializer

1. If a public class wants to call the default free initializer generated by compilation in another module, it must explicitly provide public parameter-free initialization.

1) Because the default initializer of the public class is internal level

// abc.dylib
public class Person1 {
    public init() {
        
    }
}

// testSwift
var p = Person1()

2.required initializer >= its default access level

3. If the structure has private/fileprivate storage instance attributes, then its member initializer is also private/fileprivate.

1) Otherwise, the default is internal

2) Member initializer refers to the initializer with added parameters

struct Point {
   fileprivate var x = 0
    var y = 0
}

var p1 = Point(x: 10, y: 20)

The above x is a storage attribute modified by fileprivate, then the init(x,y) member initializer is also fileprivate

10. Cases of enumeration types

1. Access levels cannot be set individually for each case of an enum.

2. Each case automatically receives the access level of enum.

1) The case defined by public enum is also public

11. Agreement

1. The access level defined in the protocol requires automatic acceptance of the protocol. The access level cannot be set separately.

1) The requirements defined by the public protocol are also public

The Runnable protocol is of internal type, so individual access level settings cannot be performed inside it.

2. The access level of the protocol implementation must be >= the access level of the type, or >= the access level of the protocol

We cannot define the access level of methods or attributes in the protocol, but we can define the access level of the specific implementation of this protocol.

internal protocol Runnable {
  func run()
}

private class dogRun: Runnable {
   fileprivate func run() {
        
    }
}

The access level of the protocol implementation above is fileprivate, the access level of the type is private, and the access level of the protocol is internal

3. There is no relationship between the access level between the protocol and the classes that comply with the protocol. The access level of the protocol is not necessarily greater than the level of the classes that comply with it.

4. Can the following code be compiled and passed?

public protocol Runnable {
func run()
}
public class Person : Runnable {
func run() {}
}

The compilation error is reported because the access level of the run() function is internal, while the access level of the Person class and Runnable protocol is public.

12. Expansion

1. If the extended access level is explicitly set, members added by the extension will automatically receive the extended sub-access level.

2. If the extended access level is not set explicitly, the default access level of members added by the extension is the same as the members defined directly in the type.

3. Access levels can be set individually for members added by the extension

4. You cannot explicitly set the access level of the extension for an extension that is used to comply with the protocol.

5. Extensions in the same file can be written as multi-part type declarations

1) Declare a private member in the original declaration, which can be accessed in the extension of the same file

2) Declare a private member in the extension, which can be accessed in other extensions and original declarations in the same file

public class Person8 {
    private func run0() { }
    private func eat0() {
        run1()
    }
}

extension Person8 {
    private func run1() { }
    private func eat1() {
        run0()
    }
}

extension Person8 {
    private func eat2() {
        run1()
    }
}

The above code has no errors and can be accessed

Supongo que te gusta

Origin blog.csdn.net/qq_43658148/article/details/134062780
Recomendado
Clasificación