5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Swift】プロトコルエクステンションについて

Posted at

型に機能を追加する際にextension(エクステンション)を使用しますが、
エクステンションはプロトコルにも定義でき、これをプロトコルエクステンションと言います。

プロトコルエクステンションは、
プロトコルが要求するインターフェースを追加するのではなく、
プロトコルに実装を追加するものになります。

##定義方法
プロトコルエクステンションを定義するには、extensionキーワードを使用します。


extension プロトコル名 {
    対象のプロトコルに実装する要素
}

次のサンプルコードでは、
Protocolプロトコルでnameプロパティとvalueプロパティを要求しています。
そこにエクステンションで実装を追加します。

エクステンションで追加した機能は準拠している型で実装する必要がありません。


protocol Protocol {
    var name: String { get }
    var value: Int { get }
}

extension Protocol {
    var product: String {
        return "\(name)\(value)円です。"
    }
}

struct Sample: Protocol {
    var name: String
    var value: Int
}

let sample = Sample(name: "圧力鍋", value: 7000)
print(sample.product)

実行結果
圧力鍋は7000円です

##デフォルト実装による実装の任意化
プロトコルに定義されているインターフェースに対して
プロトコルエクステンションで実装を追加すると、
プロトコルに準拠する型での実装は任意となります。

準拠する型が実装を再定義しなかった場合は
プロトコルエクステンションの実装が使用されるため、これをデフォルト実装と言います。

次のサンプルコードでは、
Protocolプロトコルにプロパティを3つ用意しています。

そのうちnoteプロパティはOptional<String>型にし、
このプロパティ内に値が入っているかどうかで出力結果を変えます。

Protocolプロトコルに対しエクステンションで実装の追加をしています。
今回の場合は、2つデフォルト実装を追加しています。

① noteプロパティのゲッタでnilを返すようにしています。
② productプロパティを追加しnoteプロパティがnilでない時のみ出力を変えてます。

その後、Book型とKitchenware型を定義し
Kitchenware型のみnoteプロパティに対して値を入れました。

なので2つの型の出力が変わってきます。


protocol Protocol {
    var name: String { get }
    var value: Int { get }
    var note: String? { get }
}

extension Protocol {
    var note: String? {
        return nil
    }
    
    var product: String {
        var messages = "商品名:\(name)\n価格:\(value)"
        if let note = note {
            // noteがnilじゃなかった時に実行される
            messages += "\n注意事項:\(note)"
        }
        return messages
    }
}

struct Book: Protocol {
    var name: String
    var value: Int
    // noteはnilのまま
}

struct Kitchenware: Protocol {
    var name: String
    var value: Int
    // noteに値が入った状態
    var note: String? {
        return "取り扱いにご注意ください。"
    }
}

let naruto = Book(name: "NARUTO", value: 600)
let knife = Kitchenware(name: "包丁", value: 3000)

print(naruto.product)
print("----")
print(knife.product)

実行結果
商品名:NARUTO
価格:600
----
商品名:包丁
価格:3000
注意事項:取り扱いにご注意ください

このようにデフォルト実装を与えて実装を任意にすることにより、
標準的な機能を提供しつつもカスタマイズの余地を与えることができます。

以上でプロトコルエクステンションの説明を終了します。

プロトコルは異なる型どうしに共通のプロパティやメソッドを定義し、
さらに連想型などによってそれらの型の関係性を記述します。

プトロコルを活用することで、複数の型を共通のインターフェースで扱え、
より簡潔で拡張性の高いプログラムを記述できます。

なので、プロトコルを使いこなすことができれば、
コードのメンテナンス性や可読性が高くなります。

ぜひ使えるようになりましょう!

【Swift】プロトコルの概念と定義方法
【Swift】プロトコルを構成する要素

最後までご覧いただきありがとうございました。

他にもプロトコルについての記事がありますのでぜひご覧ください。

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?