🕊

[Swift] プロトコルにプロトコルを継承させたときの挙動

2021/12/25に公開

ポイント

  • プロトコルを継承したプロトコルは継承元のプロトコルを満たさなくてもよい
    • プロトコルの要件を満たす必要があるのは継承したClass側
  • 引数としてプロトコルを設定している場合、直接そのプロトコルを継承していなくてよい
    • 間接的にそのプロトコルを継承している関係であればエラーは起こらない

実験したコード

protocol HogeProtocol {
    var hoge: Int { get }
}

protocol MogeProtocol {
    var moge: Int { get }
}

protocol MogeHogeProtocol: HogeProtocol {
    var moge: Int { get }
    // var hoge: Int { get } ← HogeProtocol プロトコルを継承しているが hoge を宣言しなくてもよい
}

protocol HogeMogeProtocol: MogeProtocol {
    // var moge: Int { get } ← MogeProtocol プロトコルを継承しているが moge を宣言しなくてもよい
    var hoge: Int { get }
}

// パターンA
class MogeClass: MogeProtocol {
    var moge: Int = 0
}

// パターンB
class HogeClass: HogeProtocol {
    var hoge: Int = 2
}

// パターンC
class MogeAndHogeClass: MogeProtocol, HogeProtocol {
    var moge: Int = 0
    var hoge: Int = 3
}

// パターンD(MogeHogeProtocolはHogeProtocolを継承している)
class MogeHogeClass: MogeHogeProtocol {
    var moge: Int = 0
    var hoge: Int = 4
}

// パターンE(HogeMogeProtocolはMogeProtocolを継承している)
class HogeMogeClass: HogeMogeProtocol {
    var moge: Int = 0
    var hoge: Int = 5
}

// パターンF(HogeMogeProtocolはMogeProtocolを継承している)
class HogeMogeAndHogeClass: HogeMogeProtocol, HogeProtocol {
    var moge: Int = 0
    var hoge: Int = 6
}

class TestClass {
    let hogeClass: HogeProtocol
    
    init(hogeClass: HogeProtocol) {
        self.hogeClass = hogeClass
        print(hogeClass.hoge)
    }
}

/// 実験
let a = TestClass(hogeClass: MogeClass()) // MogeProtocol ← HogeProtocol は継承していないのでコンパイルエラー
let b = TestClass(hogeClass: HogeClass()) // HogeProtocol
let c = TestClass(hogeClass: MogeAndHogeClass()) // MogeProtocol + HogeProtocol
let d = TestClass(hogeClass: MogeHogeClass()) // MogeHogeProtocol(HogeProtocolを継承している)
let e = TestClass(hogeClass: HogeMogeClass()) // HogeMogeProtocol(MogeProtocolを継承している) ← HogeProtocol は継承していないのでコンパイルエラー
let f = TestClass(hogeClass: HogeMogeAndHogeClass()) // HogeMogeProtocol(MogeProtocolを継承している) + HogeProtocol
GitHubで編集を提案

Discussion