Latest web development tutorials

スウィフトアクセス制御

アクセス制御は、コードアクセスレベルにソースファイルまたはコードのモジュール、他に定義することができます。

あなたが明示的にアクセスレベルを設定するための単一の型(クラス、構造体、列挙型)に、また、プロパティ、関数、初期化方法、基本的なタイプのこれらの種類を与えることができ、下付き文字のインデックスはアクセスレベルを設定します。

契約はまた、グローバル定数、変数や関数合意を含め、一定の範囲内で使用するように制限される場合があります。

ソースファイルとベースのアクセス制御モジュール。

モジュールはフレームワークやアプリケーションを構築し、公開するために別々のユニットによって定義されています。 importキーワードでスウィフトで使用可能なモジュールは、別のモジュールを紹介します。

ソースファイルは、通常はソースファイルが複数のクラスや関数を定義することができます含まれているモジュールに属する単一のソースファイルです。

プライベート、内部、公共:スウィフトはアクセスコードエンティティの3つの異なるレベルを提供します。

アクセスレベル 定義
パブリック ソース・モジュールでファイルにアクセスできる任意のエンティティは、他の人は、モジュールの導入により、すべてのエンティティのソースファイルにアクセスすることができます。
内部 :任意のソースモジュール内のファイルにアクセスすることができ、エンティティが、他はソース・モジュール・ファイルの実体にアクセスすることはできません。
プライベート 民間団体として知られている現在のソースファイルでのみエンティティを使用してください。

最も先進的なレベルへのパブリックアクセス、プライベートアクセスの最低レベルです。

文法

修飾子を公開、内部のプライベートアクセスレベルのエンティティを宣言することにより:

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

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

特別な指示がない限り、それ以外のエンティティは、デフォルトのアクセスレベルは、内部使用します。


機能タイプのアクセス

関数導出されたパラメータに基づいて、アクセスレベルは、関数の戻り値の型とアクセスのレベルの種類を必要とします。

次の例では、名前のsomeFunctionグローバル関数を定義し、明示的にアクセスレベルを肯定しません。

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

クラスSomeInternalClassアクセスレベルのいずれかで機能が内蔵され、SomePrivateClass他のアクセスレベルはプライベートです。 そのため、アクセスレベルタプルの原理に従って、タプルアクセスレベルはプライベートです。

関数が返すのでアクセスレベルの種類は、あなたがprivate修飾子を使用する必要がありますので、明示的に関数を宣言、プライベートです。
private func someFunction() -> (SomeInternalClass, SomePrivateClass) {
    // 函数实现
}

この機能は、パブリックまたは内部として宣言、または内部アクセスレベルが間違っているデフォルトを使用されています。


アクセス列挙型

アクセスレベル列挙メンバーが列挙から継承された、あなたは、アクセスの個別の宣言異なるレベルのメンバーを列挙することはできません。

たとえば、次の例、列挙学生が明示的にパブリック・レベルとして宣言され、そのメンバー名、アクセスのマークのレベルも公開されています:

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

上記プログラム実行出力は、次のとおりです。

学生成绩: 98,97,95

サブクラスアクセス

アクセスレベルサブクラスは、親クラスのアクセスのレベルを超えてはなりません。 例えば、親クラスのアクセスレベルが内部である、サブクラスのアクセスレベルは、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()

上記プログラム実行出力は、次のとおりです。

超类
子类

定数、変数、プロパティ、インデックスアクセス

定数、変数、属性は、アクセスレベルのその種類以上を持つことができません。

たとえば、パブリックプロパティのレベルを定義し、それは、コンパイラによって許可されていない民間レベルのタイプ、です。

同様に、インデックスは、インデックス型またはアクセスレベルの種類よりも高いリターンを持つことができません。

定数、変数、プロパティ、添字インデックス定義型が民間レベルであれば、彼らは明らかに民間へのアクセスレベルを明記する必要があります。

private var privateInstance = SomePrivateClass()

ゲッターとセッターのアクセス

ゲッタとセッタのアクセスレベルの定数、変数、プロパティ、添字インデックスは、彼らがメンバーに属しているアクセスのレベルから継承されました。

あなたは、変数、プロパティまたは下付きインデックス読み取りと書き込みのアクセス権を制御することができるようにセッターのアクセスレベルは、ゲッターを対応するアクセスレベルよりも低くてもよいです。

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

上記プログラム実行出力は、次のとおりです。

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

コンストラクタやデフォルトコンストラクタのアクセス

初期化

私たちは、アクセスのレベルを宣言するために初期化メソッドをカスタマイズすることができますが、それはクラスや他のアクセスのより高いレベルに属します。 しかし、必要なコンストラクタの例外が、それは彼らのクラスの同じレベルにレベルとアクセスにアクセスする必要があります。

関数やメソッドのパラメータとしては、アクセスレベルの初期化パラメータの方法は、アクセスレベルの初期化方法より小さくすることはできません。

デフォルトの初期化メソッド

スウィフトは、構造体である、クラスが割り当てを提供するために、自分の財産のすべてについて、パラメータなしでデフォルトの初期化方法を提供するが、特定の値を与えるものではありません。

デフォルトの初期化方法は、アクセスの同じレベルとアクセスレベルの種類に属します。

各サブクラスでのアクセス()initメソッドの前に必要なキーワードステートメントを使用します。

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

上記プログラム実行出力は、次のとおりです。

10
30
10

アクセス合意

あなたは明確な合意は、アクセスレベルを肯定したい場合、我々はあなたが契約だけドメインを述べたアクセスレベルの役割で使用されていることを確認したいことに注意する必要があります。

あなたは契約の必要な機能を実現するために、パブリック・アクセス・レベル・プロトコルを定義した場合には、パブリックアクセスレベルによって提供されます。 これは、公共のアクセスレベルの他のタイプ、それらの内部のメンバーのアクセスレベルなどの他のタイプとは異なります。

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

上記プログラム実行出力は、次のとおりです。

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

拡張アクセス

あなたが条件で、クラス、構造体、列挙型の拡張を可能にすることができます。 元のクラスのメンバーの拡張メンバーは、同じレベルのアクセス権を持っている必要があります。 たとえば、あなたは元のデフォルトの内部アクセスレベルの同じメンバーを持つ必要があり、新しいメンバーを追加し、一般的なタイプを拡張します。

代わりに、明示的にすべてのメンバーに拡張内(そのようなプライベート拡張の使用など)のアクセスの拡張レベルを宣言することができ、新しいデフォルトのアクセスレベルを確認します。 新しいデフォルトのアクセスレベルは、依然としてアクセスレベルによって覆われた個々のメンバーを確認しすることができます。


汎用アクセス

アクセスレベルジェネリック型またはジェネリック関数がジェネリック型、関数自体は、アクセスの3最低レベルのジェネリック型パラメータを取ります。

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

上記プログラム実行出力は、次のとおりです。

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

タイプの別名

もしエイリアスを入力するものは、アクセス制御を容易にするために、別のタイプとして定義されます。 タイプエイリアスタイプのアクセスレベルは、アクセス元のレベルよりも高くすることができません。

たとえば、プライベートクラス型の別名がパブリック、内部、民間のタイプに割り当てることができますが、パブリックレベルの型の別名が唯一の公共レベルの型に設定することができ、内部またはプライベートレベルのタイプに設定することはできません。

注:このルールは、関連するタイプ名とエイリアスにプロトコル準拠を満たすためにケースに適用されます。

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)

上記プログラム実行出力は、次のとおりです。

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