🐙

Swift プロトコルについてメモ

2024/05/18に公開

Swiftのプロトコルは型のインターフェースを定義するものです。
※インターフェース→二つのものを繋ぐ接点
インターフェースを定義し、抽象化することによって、複数のかたで共通の機能を実装することができる。
プロトコルはクラス、構造体、列挙体などで使われ、プロトコルのインターフェースを満たす型は、”プロトコルに準拠している”と言われる。

こちらより
https://swift.codelly.dev/guide/プロトコル/#プロトコルの定義方法

プロトコルの定義方法

protocol プロトコル名 {}
protocol CurryProtocal {
  func makeCurry()
}

このようにすることでCurryProtocalというprotocolを定義できました。

クラスでの準拠

class Chef:CurryProtocal {
   func makeCurry() {
       print("カリーを作ります")
  }
}

let chef = Chef()
chef.makeCurry()//カリーを作ります

構造体での準拠

struct indiaChef:CurryProtocal {
  func makeCurry() {
     print("インディアカリーを作ります")
   }
}

let indiaChef = makeCurry()
indiaChef.makeCurry()//インディアカリーを作ります

クラスと構造体の両方を使用する例

let cooks: [CurryProtocal] = [Chef,indiaChef]
for cook in cooks {
    cook.makeCurry)()
}
// "カリーを作ります"
// "インディアカリーを作ります"

プロトコルのプロパティ要件とメソッド要件

protocol CurryProtocol {
    // プロパティ要件
    var kuminpaudar: Int { get set }
    var onionsurais: Int { get }

    // メソッド要件
    func someMethod() -> String
}

プロパティ要件のget set部分について
{ get set } → 読み取りと書き込みが可能でなければならない
{ get } → 読み取りができればいい
func someMethod() -> String
someMethod: 引数を取らずに String型を返すメソッドです。

※読み取り(get)

プロパティの値を取得することを 読み取り(get)という、プロパティが読み取り可能であるということは、そのプロパティの値を外部から取得できるということ。

※書き込み(set)

プロパティの値を設定することを書き込み(set)という。プロパティが書き込み可能であるということは、そのプロパテきの値を外部から設定できることを意味する。

プロトコルの適合

クラス、構造体、列挙型がプロトコルに適合(confrom)するためには、そのプロトコルが要求するプロパティやメソッドを実装する必要がある。

protocol SomeProtocol {
 //プロパティ要件
 var mustBeSettable: Int {get set}
 var doesNotNeedToBeSettable: Int {get}

 //メソッド要件
 func someMethod() -> String

↓↓↓↓↓ プロトコルに適合(confrom)するために、プロパティとメソッドを実装
struct SomeStructure: SomeProtocol {
   var mustBeSettable: Int
   var doesNotNeedToBeSettable: Int

   func someMethod() -> String {
      return "Hello"
   }
}

SomeProtocolに準拠したSomeStructure struct

デリゲートパターン

あるオブジェクトが別のオブジェクトに対してタスクを委譲するパターン

protocol CurryDelegate {
    func CurryMake(result: String)
}

class IndiaChef {
    var delegate: CurryDelegate?

    func makingCurry() {
        // カリー作り実行
        let result = "カリー作り完了"
        delegate?.CurryMake(result: result)
    }
}

class CurryHandler: CurryDelegate {
    func CurryMake(result: String) {
        print(result)
    }
}

let indiaChef = IndiaChef()
let handler = CurryHandler()

indiaChef.delegate = handler
indiaChef.makingCurry()  // "カリー作り完了" と出力されます

というデータの流れ
IndiaChef  makingCurry デリゲートに準拠したIndiaChefクラス

CurryDelegate CurryMake CurryDelegateプロトコル

CurryHandler CurryMake デリゲートに準拠したCurryHandlerクラス

プロトコルの拡張

プロトコルは拡張(extension)を利用してデフォルト実装を提供することができる。これにより、すべての適合タイプに共通の動作を提供することができる。

extension SomeProtocol {
  func someMethod() -> String {
     return "Default Impkementation"
   }
}

ここで覚えておくことは、
プロトコルは、異なる型間で共通の機能を持たせたり
デリゲートパターンを使用して、クラス間の通信を実現したりできる。

Discussion