プロトコルは protocol で宣言します。

protocol ExampleProtocol {
    var simpleDescription: String { get }
    mutating func adjust()
}

クラス、列挙型、構造体は、すべてプロトコルを定義することができます。

class SimpleClass: ExampleProtocol {
    var simpleDescription: String = "A very simple class."
    var anotherProperty: Int = 69105
    func adjust() {
        simpleDescription += "  Now 100% adjusted."
    }
}
var a = SimpleClass()
a.adjust()
let aDescription = a.simpleDescription

struct SimpleStructure: ExampleProtocol {
    var simpleDescription: String = "A simple structure"
    mutating func adjust() {
        simpleDescription += " (adjusted)"
    }
}
var b = SimpleStructure()
b.adjust()
let bDescription = b.simpleDescription
EXPERIMENT
このプロトコルに準拠する列挙型 (enum) を書いてみよう。

SimpleStructure の宣言で、構造体 (struct) を変更するメソッドのキーワード mutating に注目してください。クラスのメソッドは、常にクラスを変更することができるため、SimpleClass の宣言には mutating キーワードは必要ありません。

メソッドやプロパティ (computed properties) のように、既存の型に機能を追加する目的で extension を使用します。他のところで宣言されている型に対して、プロトコルに準拠するようエクステンションを使うことができます。さらには、ライブラリやフレームワークからインポートした型に対してでもエクステンションを利用可能です。

extension Int: ExampleProtocol {
    var simpleDescription: String {
        return "The number \(self)"
    }
    mutating func adjust() {
        self += 42
    }
}
print(7.simpleDescription)
EXPERIMENT
Double 型に absoluteValue プロパティを追加するエクステンションを書いてみよう。

プロトコル名を他の名前付き型(クラス、列挙型、構造体)と同じように利用することが可能です。例えば、あるプロトコルに準拠する異なる型のオブジェクトをコレクションとして持つことができます。プロトコルの型を扱っているとき、プロトコルで定義されていないメソッドを利用することはできません。

let protocolValue: ExampleProtocol = a
print(protocolValue.simpleDescription)
// print(protocolValue.anotherProperty)  // エラーを確認するためにコメントを外す

変数 protocolValue の実行時の型は SimpleClass でありながら、この例では、指定された型の ExampleProtocol としてコンパイラは扱います。そのため、プロトコル準拠とは別にクラスが追加実装しているメソッドやプロパティに、アクセスできてしまうということはありません。


Portions of this page are translations based on work created and shared by Apple and used according to terms described in the Creative Commons Attribution 4.0 International License.