0

Swift でのプロトコル指向プログラミングと、拡張機能のしくみと提供できる拡張性のレベルについて理解しようとしています。

Playgrounds で実行した次のコード スニペットを用意します。

protocol ProtocolA {
    func doSomethingA()
}

protocol ProtocolB {
    func doSomethingB()
}

protocol ProtocolC {
    func doSomethingC()
}

extension ProtocolA {
    func doSomethingA() {
        print("Extension - doSomethingA")
    }
}

extension ProtocolA where Self: ProtocolB {
    func doSomethingA() {
        print("Extension - doSomethingA Self: ProtocolB")
    }
}

extension ProtocolA where Self: ProtocolC {
    func doSomethingA() {
        print("Extension - doSomethingA Self: ProtocolC")
    }
}

extension ProtocolA where Self: ProtocolB, Self: ProtocolC {
    func doSomethingA() {
        print("Extension - doSomethingA Self: ProtocolB, ProtocolC")
    }
}

extension ProtocolB {
    func doSomethingB() {
        print("Extension - doSomethingB")
    }
}

extension ProtocolC {
    func doSomethingC() {
        print("Extension - doSomethingC")
    }
}

class Implementation: ProtocolA, ProtocolB, ProtocolC {
}

let obj = Implementation()

obj.doSomethingA()

私が印刷するものは次のとおりです。

Extension - doSomethingA Self: ProtocolB, ProtocolC

とにかく、すべての拡張機能が実行されることを保証できますか?

理想的には、次の出力を得たいと思います。

Extension - doSomethingA
Extension - doSomethingA Self: ProtocolB
Extension - doSomethingA Self: ProtocolC
Extension - doSomethingA Self: ProtocolB, ProtocolC

私は、Swift が型に関して最も強い一致を選択することを理解しています。実際、ProtocolA が ProtocolB と ProtocolC の両方に一致する実装を提供しないと、コンパイル時エラーが発生します。これを回避できる方法はありますか?

ありがとう。

4

1 に答える 1

2

拡張のポイントは、プロトコル メソッドのデフォルトの実装を提供することです。

あなたの例では、コンパイラはdoSomethingA()具体的なオブジェクトに最適な拡張機能のメソッドを呼び出すように解決しますが、それだけです。

あなたの電話番号でわかるように:

obj.doSomethingA()

1 つのメソッド呼び出しを実行しています。これは解決され、4 つではなく 1 つのメソッド呼び出しにディスパッチされます。

これは、サブクラス化によってメソッドをオーバーライドし、基本クラスのメソッドを呼び出す場合に似ています。基本クラスのメソッドではなく、派生メソッドのみが呼び出されます。その場合、必要に応じsuper.method()てサブクラスから呼び出すことができます。

あなたの場合、複数のメソッドを呼び出す必要がある場合は、拡張機能を介して個別の名前と実装を指定し、次のようにすべてのプロトコルを実装するクラスを作成するだけです。

class A: ProtocolA, ProtocolB, ProtocolC {

   func all() {
      doSomethingA()
      doSomethingB()
      doSomethingC()
   }
}

ここでの拡張機能の利点はclass A、3 つのメソッドの実装を提供する必要がないことです。

于 2016-07-04T10:03:16.970 に答える