【Swift】 protocolを利用して、抽象クラスの振る舞いをさせる方法

  • 4
    Like
  • 0
    Comment

基底クラスに処理の流れを記述し、実際の処理は派生クラスで記述したい事があると思います。
C++などの言語にはこの要求に応える為 抽象クラス(abstract class) という概念が用意されているのですが、Swiftには残念ながら抽象クラスは存在しません。
抽象クラスと同じ振る舞いをさせたい場合、protocolを利用することになります。

サンプルは次の要件で実装します。
1. 基底クラス BaseClass に処理の流れを定義する
2. 基底クラスはインスタンス化を禁止する
3. 処理の流れに使うメソッドはプロトコル ClassFrameworkProtocol に定義する
4. 派生クラス SubClass に実際の処理を記述する
5. 派生クラスは ClassFrameworkProtocol プロトコルを採用することを義務付ける


ClassFrameworkProtocol プロトコルの実装

protocol ClassFrameworkProtocol: class {
    func a()
    func b()
    func c()
}

派生クラスで実装してもらいたいメソッド群を定義します。


基底クラスの実装

class BaseClass {
    required init() {
        assert(type(of: self) != BaseClass.self, "BaseClassはインスタンス化に対応していません")
        assert(self is ClassFrameworkProtocol, "ClassFrameworkProtocolを採用する必用があります")

        self.work()
    }

    func work() {
        if let obj = self as? ClassFrameworkProtocol {
            obj.a()
            obj.b()
            obj.c()
        }
    }
}

init() に要件2と5を満たす為のチェックを記述しています。
work() に処理の流れを記述しています。


派生クラスの実装

class SubClass: BaseClass {}

extension SubClass: ClassFrameworkProtocol {
    func a() {
        debugPrint(#function)
    }

    func b() {
        debugPrint(#function)
    }

    func c() {
        debugPrint(#function)
    }
}

プロトコロル ClassFrameworkProtocol を採用し、各メソッドの処理を記述しています。


実行結果

let obj = SubClass()
"a()"
"b()"
"c()"

要件2の検証

let baseObj = BaseClass()
assertion failed: BaseClassはインスタンス化に対応していません

要件5の検証

class NotAdoptedSubClass: BaseClass {}
let obj = NotAdoptedSubClass()
assertion failed: ClassFrameworkProtocolを採用する必用があります