Edited at

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

More than 1 year has passed since last update.

基底クラスに処理の流れを記述し、実際の処理は派生クラスで記述したい事があると思います。

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を採用する必用があります