14
18

More than 5 years have passed since last update.

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

Last updated at Posted at 2017-02-21

基底クラスに処理の流れを記述し、実際の処理は派生クラスで記述したい事があると思います。
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を採用する必用があります
14
18
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
18