迅速なプロトコル


プロトコルは、特定の機能を実装するために必要なメソッドと属性を指定します。

プロトコルの要件を満たすことができるタイプはすべて、プロトコルに準拠していると言われます。

クラス、構造体、または列挙型はすべてプロトコルに従い、プロトコルで定義されたメソッドと関数を完成させるための特定の実装を提供できます。

文法

プロトコルの構文形式は次のとおりです:

protocol SomeProtocol {
    // 协议内容
}

クラスを特定のプロトコルに従わせるには、型名の後にプロトコル名をコロンで区切って追加する必要があります。型定義の。複数のプロトコルに従う場合は、それらをカンマで区切ります。

struct SomeStructure: FirstProtocol, AnotherProtocol {
    // 结构体内容
}

プロトコルに準拠しているクラスに親クラスがある場合は、親クラス名をカンマで区切ってプロトコル名の前に配置する必要があります。

class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol {
    // 类的内容
}

プロパティのプロビジョニング

このプロトコルは、保存されたプロパティであるか計算されたプロパティであるかを指定せずに、特定のインスタンス プロパティまたはクラス プロパティを指定するために使用されます。さらに、読み取り専用か読み取りおよび書き込み可能かを指定する必要があります。

プロトコルでは、通常、変数の属性を宣言するために var が使用され、属性が読み取り可能および書き込み可能であることを示すために { set get } が追加されます。

protocol classa {
    
    var marks: Int { get set }
    var result: Bool { get }
    
    func attendance() -> String
    func markssecured() -> String
    
}

protocol classb: classa {
    
    var present: Bool { get set }
    var subject: String { get set }
    var stname: String { get set }
    
}

class classc: classb {
    var marks = 96
    let result = true
    var present = false
    var subject = "Swift 协议"
    var stname = "Protocols"
    
    func attendance() -> String {
        return "The \(stname) has secured 99% attendance"
    }
    
    func markssecured() -> String {
        return "\(stname) has scored \(marks)"
    }
}

let studdet = classc()
studdet.stname = "Swift"
studdet.marks = 98
studdet.markssecured()

print(studdet.marks)
print(studdet.result)
print(studdet.present)
print(studdet.subject)
print(studdet.stname)

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

98
true
false
Swift 协议
Swift

Mutating メソッドのプロビジョニング

場合によっては、メソッド内のインスタンスを変更する必要があります。

たとえば、値型 (構造体、列挙型) のインスタンス メソッドでは、変化するキーワードが関数のプレフィックスとして使用され、func の前に記述され、それが属するインスタンスとそのインスタンス属性の値を示します。この方法で変更できます。

protocol daysofaweek {
    mutating func show()
}

enum days: daysofaweek {
    case sun, mon, tue, wed, thurs, fri, sat
    mutating func show() {
        switch self {
        case sun:
            self = sun
            print("Sunday")
        case mon:
            self = mon
            print("Monday")
        case tue:
            self = tue
            print("Tuesday")
        case wed:
            self = wed
            print("Wednesday")
        case mon:
            self = thurs
            print("Thursday")
        case tue:
            self = fri
            print("Friday")
        case sat:
            self = sat
            print("Saturday")
        default:
            print("NO Such Day")
        }
    }
}

var res = days.wed
res.show()

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

Wednesday

コンストラクターのプロビジョニング

プロトコルは、そのフォロワーに指定されたコンストラクターの実装を要求できます。

コンストラクターの宣言は、通常のコンストラクターを記述するのと同じようにプロトコル定義に記述できますが、中括弧とコンストラクターの実体を記述する必要はありません。構文は次のとおりです。

protocol SomeProtocol {
   init(someParameter: Int)
}

Example

protocol tcpprotocol {
   init(aprot: Int)
}

プロトコルコンストラクター クラスに実装を指定します

このプロトコルに従うクラスにコンストラクターを実装し、クラスの指定初期化子またはコンビニエンス初期化子として指定できます。どちらの場合も、コンストラクター実装を「required」修飾子でマークする必要があります:

class SomeClass: SomeProtocol {
   required init(someParameter: Int) {
      // 构造器实现
   }
}

protocol tcpprotocol {
   init(aprot: Int)
}

class tcpClass: tcpprotocol {
   required init(aprot: Int) {
   }
}

required 修飾子を使用すると、このプロトコルに従うすべてのサブクラスも明示的なコンストラクター仕様または継承された実装を提供できるようになります。

サブクラスが親クラスの指定されたコンストラクターをオーバーライドし、そのコンストラクターが特定のプロトコルの規定に準拠している場合、コンストラクターの実装は required 修飾子と override 修飾子の両方でマークする必要があります:

protocol tcpprotocol {
    init(no1: Int)
}

class mainClass {
    var no1: Int // 局部变量
    init(no1: Int) {
        self.no1 = no1 // 初始化
    }
}

class subClass: mainClass, tcpprotocol {
    var no2: Int
    init(no1: Int, no2 : Int) {
        self.no2 = no2
        super.init(no1:no1)
    }
    // 因为遵循协议,需要加上"required"; 因为继承自父类,需要加上"override"
    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

プロトコルタイプ

プロトコル自体は何も実装していませんが、プロトコルをタイプとして使用することができます。

プロトコルは、他の通常の型、使用シナリオと同様に使用できます:

  • 関数、メソッド、またはコンストラクターのパラメーター型または戻り値の型として

  • 定数、変数、またはプロパティの型として

  • 要素の型として配列、辞書、または他のコンテナ内

インスタンス

protocol Generator {
    typealias members
    func next() -> members?
}

var items = [10,20,30].generate()
while let x = items.next() {
    print(x)
}

for lists in [1,2,3].map( {i in i*5}) {
    print(lists)
}

print([100,200,300])
print([1,2,3].map({i in i*10}))

上記のプログラム実行の出力結果は次のとおりです:

10
20
30
5
10
15
[100, 200, 300]
[10, 20, 30]

拡張機能にプロトコル メンバーを追加します

拡張機能を使用して既存の型 (クラス、構造体、列挙型など) を拡張できます。

拡張機能は、属性、メソッド、添え字スクリプト、プロトコル、その他のメンバーを既存の型に追加できます。

protocol AgeClasificationProtocol {
   var age: Int { get }
   func agetype() -> String
}

class Person {
   let firstname: String
   let lastname: String
   var age: Int
   init(firstname: String, lastname: String) {
      self.firstname = firstname
      self.lastname = lastname
      self.age = 10
   }
}

extension Person : AgeClasificationProtocol {
   func fullname() -> String {
      var c: String
      c = firstname + " " + lastname
      return c
   }
   
   func agetype() -> String {
      switch age {
      case 0...2:
         return "Baby"
      case 2...12:
         return "Child"
      case 13...19:
         return "Teenager"
      case let x where x > 65:
         return "Elderly"
      default:
         return "Normal"
      }
   }
}

プロトコルの継承

プロトコルは 1 つ以上の他のプロトコルを継承でき、継承されたプロトコルに基づいて新しいコンテンツ要件を追加できます。

プロトコルの継承構文はクラスの継承と似ています。複数の継承されたプロトコルはカンマで区切られます:


Instance

protocol InheritingProtocol: SomeProtocol, AnotherProtocol {
    // 协议定义
}

上記のプログラムの実行の出力結果は次のとおりです:

protocol Classa {
    var no1: Int { get set }
    func calc(sum: Int)
}

protocol Result {
    func print(target: Classa)
}

class Student2: Result {
    func print(target: Classa) {
        target.calc(1)
    }
}

class Classb: Result {
    func print(target: Classa) {
        target.calc(5)
    }
}

class Student: Classa {
    var no1: Int = 10
    
    func calc(sum: Int) {
        no1 -= sum
        print("学生尝试 \(sum) 次通过")
        
        if no1 <= 0 {
            print("学生缺席考试")
        }
    }
}

class Player {
    var stmark: Result!
    
    init(stmark: Result) {
        self.stmark = stmark
    }
    
    func print(target: Classa) {
        stmark.print(target)
    }
}

var marks = Player(stmark: Student2())
var marksec = Student()

marks.print(marksec)
marks.print(marksec)
marks.print(marksec)
marks.stmark = Classb()
marks.print(marksec)
marks.print(marksec)
marks.print(marksec)


Class -特定のプロトコル

プロトコルの継承リストに class キーワードを追加することで、プロトコルをクラス タイプにのみ適用できます。

class キーワードは、プロトコルの継承リストに最初に出現するキーワードでなければならず、その後に他の継承されたプロトコルが続きます。形式は次のとおりです:

学生尝试 1 次通过
学生尝试 1 次通过
学生尝试 1 次通过
学生尝试 5 次通过
学生尝试 5 次通过
学生缺席考试
学生尝试 5 次通过
学生缺席考试

Example

protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol {
    // 协议定义
}

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

protocol TcpProtocol {
    init(no1: Int)
}

class MainClass {
    var no1: Int // 局部变量
    init(no1: Int) {
        self.no1 = no1 // 初始化
    }
}

class SubClass: MainClass, TcpProtocol {
    var no2: Int
    init(no1: Int, no2 : Int) {
        self.no2 = no2
        super.init(no1:no1)
    }
    // 因为遵循协议,需要加上"required"; 因为继承自父类,需要加上"override"
    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)")


プロトコル合成

Swift は複数のプロトコルの合成をサポートしており、同時に複数のプロトコルに従う必要がある場合に非常に役立ちます。時間。

構文形式は次のとおりです:

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

protocol<SomeProtocol, AnotherProtocol>

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

protocol Stname {
    var name: String { get }
}

protocol Stage {
    var age: Int { get }
}

struct Person: Stname, Stage {
    var name: String
    var age: Int
}

func show(celebrator: protocol<Stname, Stage>) {
    print("\(celebrator.name) is \(celebrator.age) years old")
}

let studname = Person(name: "Priya", age: 21)
print(studname)

let stud = Person(name: "Rehan", age: 29)
print(stud)

let student = Person(name: "Roshan", age: 19)
print(student)


プロトコルの一貫性を確認します

is および as 演算子を使用して、特定のプロトコルが一致しているかどうかを確認できます。プロトコルに従うか、特定のタイプへの変換を強制します。

  • is 演算子は、インスタンスが特定の プロトコル準拠しているかどうかをチェックするために使用されます。

    is操作符用来检查实例是否遵循了某个协议

  • as?返回一个可选值,当实例遵循协议时,返回该协议类型;否则返回nil

  • as

  • as?インスタンスがプロトコルに従う場合はオプションの値を返し、それ以外の場合はnilを返します。

as は、下方変換を強制するために使用されます。強制変換が失敗すると、実行時エラーが発生します。

例🎜🎜 次の例は、Double 型の読み取り可能領域を必要とする HasArea プロトコルを定義します: 🎜
Person(name: "Priya", age: 21)
Person(name: "Rehan", age: 29)
Person(name: "Roshan", age: 19)
🎜 上記のプログラム実行の出力結果は次のとおりです: 🎜
protocol HasArea {
    var area: Double { get }
}

// 定义了Circle类,都遵循了HasArea协议
class Circle: HasArea {
    let pi = 3.1415927
    var radius: Double
    var area: Double { return pi * radius * radius }
    init(radius: Double) { self.radius = radius }
}

// 定义了Country类,都遵循了HasArea协议
class Country: HasArea {
    var area: Double
    init(area: Double) { self.area = area }
}

// Animal是一个没有实现HasArea协议的类
class Animal {
    var legs: Int
    init(legs: Int) { self.legs = legs }
}

let objects: [AnyObject] = [
    Circle(radius: 2.0),
    Country(area: 243_610),
    Animal(legs: 4)
]

for object in objects {
    // 对迭代出的每一个元素进行检查,看它是否遵循了HasArea协议
    if let objectWithArea = object as? HasArea {
        print("面积为 \(objectWithArea.area)")
    } else {
        print("没有面积")
    }
}
🎜