やぎ星人です。どうもこんにちは。
本記事の投稿日時は2020年7月29日となっておりますが、実際は2022年1月27日に執筆中です。
理由はこちらの記事にも記載しておりますが、ものづくり活動をスタートして、ブログを後追いで立ち上げたため、このような形となっております。
(投稿日時は実際にプロジェクト活動を行った日に合わせています)
スマートカーテン開発は既に完了しており、記事をのんびりと投稿する予定だったのですが…
サボり過ぎた( ;∀;)
実際の開発~ブログ記事作成まで1年以上空いてるわけですが、この空白の期間が長くなるほど記憶を掘り返すエネルギーが必要になるのです。
本ブログの意義として、自身の学習成果をOUTPUTする環境を設けることで「より理解を深めたい」「モチベーションを向上/維持したい」という前向きな思いがありました。
初心に立ち返り、再出発したいと思います。
記事は早めに書こうね
さて、ここから本題です。
前回の記事でCoreBluetoothフレームワークを取り扱う際に、「デリゲート」とう概念が登場しました。
Swift初心者の私には何のことやらサッパリ┐(´ー`)┌
書籍やインターネットで情報収集しました。
デリゲート(delegate)について理解したこと
前回の記事で触れた「デリゲート」という仕組みについて、ご紹介させていただきます。
※Swift言語開発における「デリゲート」を対象としております
デリゲートとは
「デリゲート」について知り得た事を、私の解釈を織り交ぜながら説明させていただきます。
誤った解釈がありましたらコメント欄で優しくご指摘ください。
デリゲート それはデザインパターン
初めに勘違いしていたのが、Swift言語にデリゲートという言語仕様が存在していると思っていたのですが、実際は単なるデザインパターンの一種でした。
言い換えると、設計のテクニックの一つといったところでしょうか。
デリゲート 直訳すると「委譲」
delegate(デリゲート)を直訳すると「委譲」となります。
あるオブジェクトの処理を他のオブジェクトに委ね、実行権を譲り渡すイメージとのこと。
一言でいうとコールバック?
簡単にイメージを描いてみました。
印象としては「コールバック」という表現がしっくりきました。
- CBCentralManagerインスタンスを生成します。
- 委譲先のインスタンス情報(コールバック先)を登録します。
ここではBleHandlerインスタンスを委譲先とするため、”self”を設定します。 - CBCentralManagerにて、委譲先の処理を呼び出します。
CBCentralManagerインスタンス目線で見ると、委譲先が誰かは意識しない仕組みとなっています。
委譲先は”2″のタイミングで外部より設定されるため、CBCentralManagerインスタンスとしては単に設定された委譲先の処理を呼び出すのみとなります。
実装方法
Swiftではプロトコルという言語仕様を用いて、デリゲートの仕組みを実現します。
前提知識 ~プロトコル~
プロトコルとは、クラス/構造体/列挙型などの型で使用される規則の集合体です。
規則 = その型が備える必要があるメソッドやプロパティ
例えば、「自動車」というプロトコルを定義するとします。
「自動車」には、「走る」、「曲がる」、「止まる」というメソッドを備える必要があることを定義するには、次のように記述します。
protocol Automobile {
func driving() // 走る
func turning() // 曲がる
func braking() // 止まる
}
例えば、上記のプロトロコルを「バス」クラスに適用する場合、次のような記述になります。
「バスクラス」には、「自動車」プロトコルを適用しているため、 「走る」、「曲がる」、「止まる」 メソッドを実装しないとコンパイルエラーとなります。
class Bus: Automobile {
func driving(){
…
}
func turning(){
…
}
func braking()
…
}
}
Swiftは「プロトコル指向言語」と呼ばれているそうです。
プロトコルは言語仕様の基本概念になっており、Swiftを本格的に学ぶためには重要な要素になりそうです。
デリゲートの実装
前述したプロトコルを使用し、デリゲートの仕組みを実現します。
イメージとしては委譲元にてプロトコルを定義し、委譲先でそのプロトコルに適用(準拠)させます。
委譲元
protocol AutomobileDelegate {
func processAtFailure()
}
class Car {
var delegate: AutomobileDelegate?
…
func failuerJudgment{
…
if( XXX == YYY ){
// デリゲート:故障を検出時の処理
self.delegate.processAtFailure()
}
}
…
}
委譲先
// Highwayクラス :AutomobileDelegateプロトコルに準拠
class Highway :AutomobileDelegate {
let ponimaruCar = Car()
// コンストラクタ
init(){
// 委譲先に自オブジェクトを指定
ponimaruCar.delegate = self
}
…
// デリゲート時の実際の処理
func processAtFailure(){
…
}
…
}
「Highway」クラスで自身を委譲先に設定しましたが、他のオブジェクトを委譲先に設定することも可能です。その場合、委譲先のオブジェクトが「AutomobileDelegate」プロトコルに準拠したインスタンスであることが必須条件となります。
おわりに
以上、デリゲートについて私が学習したことを綴りました。
少しずつではありますが、自身の知らないことを学ぶのは非常に楽しいですね。
私は学生時代を含め10年以上C言語プレイヤーとして生きてきました。
今はこういった新しい開発言語を趣味の範囲で触っていますが、これを仕事として扱えるよう精進したいと思います。
有識者の方へ
誤った記述等ありましたらコメント欄で優しくご指摘ください。
それではまた次回の記事でお会いしましょう!
コメント