Swift-アクセス制御

コードブロックへのアクセスを制限するために、モジュールと抽象化はアクセス制御を通じて行われます。クラス、構造、および列挙は、アクセス制御メカニズムによって、プロパティ、メソッド、初期化子、および添え字に従ってアクセスできます。プロトコル内の定数、変数、および関数は制限されており、アクセス制御を通じてグローバルおよびローカルとしてアクセスが許可されています。プロパティ、タイプ、および機能に適用されるアクセス制御は、「エンティティ」と呼ばれます。

アクセス制御モデルは、モジュールとソースファイルに基づいています。

モジュールは、コード配布の単一ユニットとして定義されており、キーワード「import」を使用してインポートできます。ソースファイルは、複数のタイプと機能にアクセスするためのモジュール内の単一のソースコードファイルとして定義されます。

3つの異なるアクセスレベルがSwift4言語によって提供されます。それらは、パブリック、内部、およびプライベートアクセスです。

S.No アクセスレベルと定義
1

Public

エンティティを、定義モジュールの任意のソースファイル、定義モジュールをインポートする別のモジュールのソースファイルで処理できるようにします。

2

Internal

エンティティを定義モジュールの任意のソースファイル内で使用できるようにしますが、そのモジュール外のソースファイル内では使用できません。

3

Private

エンティティの使用を独自の定義ソースファイルに制限します。プライベートアクセスは、特定のコード機能の実装の詳細を隠す役割を果たします。

構文

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

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

機能タイプのアクセス制御

一部の関数では、戻り値なしで関数内で引数が宣言されている場合があります。次のプログラムは、sum()関数の引数としてaとbを宣言します。関数自体の内部では、引数aとbの値は、関数呼び出しsum()を呼び出すことによって渡され、その値が出力されるため、戻り値が削除されます。関数の戻り値の型をプライベートにするには、private修飾子を使用して関数の全体的なアクセスレベルを宣言します。

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)

遊び場を使用して上記のプログラムを実行すると、次の結果が得られます-

30 20
50 40
30 24

列挙型のアクセス制御

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

遊び場を使用して上記のプログラムを実行すると、次の結果が得られます-

Student Marks are: 98,97,95

Swift 4言語の列挙型は、列挙型の個々のケースに対して同じアクセスレベルを自動的に受け取ります。たとえば、3つのサブジェクトで保護された学生の名前とマークにアクセスすると、列挙名は学生として宣言され、列挙クラスに存在するメンバーは文字列データ型に属する名前であり、マークはデータ型Integerのmark1、mark2、mark3として表されます。生徒の名前または採点したマークにアクセスするため。これで、switch caseは、そのケースブロックが実行された場合に学生名を印刷し、そうでない場合は、学生によって保護されたマークを印刷します。両方の条件が失敗した場合、デフォルトのブロックが実行されます。

サブクラスのアクセス制御

Swift 4を使用すると、ユーザーは現在のアクセスコンテキストでアクセスできる任意のクラスをサブクラス化できます。サブクラスは、そのスーパークラスよりも高いアクセスレベルを持つことはできません。ユーザーは、内部スーパークラスのパブリックサブクラスを作成することを制限されています。

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

遊び場を使用して上記のプログラムを実行すると、次の結果が得られます-

Welcome to Swift Super Class
Welcome to Swift Sub Class

定数、変数、プロパティ、および添え字のアクセス制御

Swift 4の定数、変数、またはプロパティは、そのタイプよりもパブリックとして定義することはできません。プライベートタイプでパブリックプロパティを作成することは無効です。同様に、添え字はそのインデックスまたは戻り値の型よりも公開することはできません。

定数、変数、プロパティ、または添え字がプライベートタイプを使用する場合、定数、変数、プロパティ、または添え字もプライベートとしてマークする必要があります-

private var privateInstance = SomePrivateClass()

ゲッターとセッター

定数、変数、プロパティ、および添え字のゲッターとセッターは、それらが属する定数、変数、プロパティ、または添え字と同じアクセスレベルを自動的に受け取ります。

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

遊び場を使用して上記のプログラムを実行すると、次の結果が得られます-

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

イニシャライザーとデフォルトのイニシャライザーのアクセス制御

カスタム初期化子には、初期化するタイプ以下のアクセスレベルを割り当てることができます。必要な初期化子は、それが属するクラスと同じアクセスレベルを持っている必要があります。イニシャライザーのパラメーターのタイプは、イニシャライザー自身のアクセスレベルよりもプライベートにすることはできません。

initialize'required 'キーワードのすべてのサブクラスを宣言するには、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()

遊び場を使用して上記のプログラムを実行すると、次の結果が得られます-

10
30
10

デフォルトの初期化子は、その型がパブリックとして定義されていない限り、初期化する型と同じアクセスレベルを持ちます。デフォルトの初期化がパブリックとして定義されている場合、それは内部と見なされます。ユーザーが別のモジュールで引数なしの初期化子を使用してパブリック型を初期化できるようにする必要がある場合は、型の定義の一部として引数なしのパブリック型初期化子を明示的に指定します。

プロトコルのアクセス制御

既存のプロトコルから機能を継承するために新しいプロトコルを定義する場合、互いのプロパティを継承するには、両方を同じアクセスレベルとして宣言する必要があります。Swift 4のアクセス制御では、ユーザーは「内部」プロトコルから継承する「パブリック」プロトコルを定義できません。

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

遊び場を使用して上記のプログラムを実行すると、次の結果が得られます-

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

拡張機能のアクセス制御

Swift 4では、ユーザーがその拡張機能を使用してプロトコル準拠を追加する場合、その拡張機能に明示的なアクセスレベル修飾子を提供することはできません。拡張機能内の各プロトコル要件実装のデフォルトのアクセスレベルには、独自のプロトコルアクセスレベルが用意されています。

ジェネリック医薬品のアクセス制御

ジェネリックスを使用すると、ユーザーは最小アクセスレベルを指定して、型パラメーターの型制約にアクセスできます。

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

遊び場を使用して上記のプログラムを実行すると、次の結果が得られます-

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

タイプエイリアスのアクセス制御

ユーザーは、タイプエイリアスを定義して、個別のアクセス制御タイプを処理できます。同じアクセスレベルまたは異なるアクセスレベルをユーザーが定義できます。タイプエイリアスが「private」の場合、その関連メンバーは「private、internal ofpublictype」として宣言できます。タイプエイリアスがパブリックの場合、メンバーを「内部」または「プライベート」名としてエイリアスにすることはできません

定義したタイプエイリアスは、アクセス制御の目的で個別のタイプとして扱われます。タイプエイリアスは、エイリアスするタイプのアクセスレベル以下のアクセスレベルを持つことができます。たとえば、プライベートタイプのエイリアスはプライベートタイプ、内部タイプ、またはパブリックタイプのエイリアスを作成できますが、パブリックタイプのエイリアスは内部タイプまたはプライベートタイプのエイリアスを作成できません。

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)

遊び場を使用して上記のプログラムを実行すると、次の結果が得られます-

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

Swiftのエンコードとデコード

Swift4は新しい Codable プロトコル。特別なコードを記述せずに、また値型を失うことを心配することなく、カスタムデータ型をシリアル化および逆シリアル化できます。

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

LangauageがCodableProtocolに準拠していることに注意してください。次に、1行の単純な行を使用してJsonデータ表現に変換します。

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

Swiftは、データ型内のすべての値を自動的にエンコードします。

次のようなデコーダー機能を使用してデータをデコードできます

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

JSONEncoderとそれに対応するプロパティリストPropertyListEncoderには、動作をカスタマイズするための多くのオプションがあります。