プロトコル拡張で条件をつけたり、特定のプロトコル拡張のメソッドを呼ぶ方法

Swiftプロトコル拡張の動きが気になったので調べた結果を備忘録として残しておく。

プロトコル拡張で条件を定義

特定プロトコルの場合だけ挙動を変える。

protocol A {}
protocol B {}

extension A {
    func say() {
        print("A")
    }
}
extension A where Self : B {
    func say() {
        print("B")
    }
}

class User: A, B {}
class Author: A {}

User().say() // B
Author().say() // A

プロトコル、クラスのどちらが優先されるか?

クラスが優先された。

protocol A {}
protocol B {}

extension A {
    func say() {
        print("A")
    }
}
extension A where Self : B {
    func say() {
        print("B")
    }
}

extension A where Self : User {
    func say() {
        print("User")
    }
}

class User: A, B {}
class Author: A {}

User().say() // User
Author().say() // A

プロトコル拡張のメソッドを呼ぶ

プロトコルにキャストすれば呼べる。

protocol A {}
protocol B {}

extension A {
    func say() {
        print("A")
    }
}
extension A where Self : B {
    func say() {
        print("B")
    }
}

extension A where Self : User {
    func say() {
        print("User")
    }
}

class User: A, B {
    func say() {
        (self as A).say()
    }
}
class Author: A {}

User().say() // A
Author().say() // A