デリゲートはよくわかりませんでした。だから、それをとても簡単に説明したいと思います。
Swiftです。
(※注意。僕はエンジニアではないので、間違いなどあったらごめんなさい。ご指摘頂けるととても嬉しいです。)
どうでもよい追記:
=> エンジニアのお仕事頂けるようになったので、一応駆け出しエンジニアくらいにはなれました!(^^)/
どうしてデリゲートは分かりにくいのか。
僕はこう思います。
- 登場人物がはっきりしていない。
- 定義がはっきりしていない。
(はっきしているかもしれないけど、僕ははっきり理解できなかった。)
ちなみに、上の2つの曖昧なモノのうち、1つは今だに曖昧です。それでも大丈夫です。デリゲートとプロトコルについては理解できます。
登場人物だけおさえれば理解はできると思います。
まずは定義について
教科書(The Swift Programing Language)を読んでみますと、次のようにあります。
Delegation is a design pattern that enables a class or structure to hand off(or delegate) some of its responsibilities to an instance of another type.
簡単に言うと、こうです。
「デリゲートは、デザインパターンです。」
ここで僕は、生まれて初めて「デザインパターン」に出逢いました。
感動的な出逢いです。よく分からないものを調べたら、よく分からないものに出逢う。これ以上の探索をする気がいっきに失せます。
すでに諦めモードですが、せっかくなので、デザインパターンの定義をしらべてみました。個人的には一番すっきりしている定義は以下です。
A design pattern is a repeatable solution to a software engineering problem. (from techopedia)
ということで、デザインパタンの定義について雰囲気だけわかりました…。
分からない部分を無視してデリゲートを簡単に言えば、
「あるクラスは、他のクラスのインスタンスに、処理を任せることができる。」というようなこと。
登場人物について
本題に入ります。登場人物が分かれば、おしまいです。
登場人物は3人。
- 処理を依頼する人
- 依頼される人(代理人)
- プロトコル
以上です。
例をつくります。
依頼するクラスを「Hoge」とします。
依頼される代理人クラスを「Piyo」とします。
そして、そのために使われるプロトコルを「Mochi」としておきます。
表示にすると以下のような感じです。
例)
依頼するクラス | プロトコル | 依頼されるクラス |
---|---|---|
Hoge | Mochi | Piyo |
依頼する人 | -> | 代理人 |
もう、分かったようなものです。
コードを書いてみます。
Xcode6のplaygroundを使ってコードを書きます。これで説明は終わりです。
// プロトコルを作る。
protocol Mochi {
func sayHello() -> String
}
// 依頼人クラス
class Hoge {
// ここで、プロトコルに従うクラスのインスタンスを用意する。
var delegate: Mochi!
func say() -> String {
return delegate.sayHello()
}
}
// 代理人クラス。クラスの後ろにプロトコルを書く。
class Piyo: Mochi {
func sayHello() -> String {
return "Hello, Piyopiyo"
}
}
let hoge = Hoge()
let piyo = Piyo()
hoge.delegate = piyo // 代理人を指定。
hoge.say() // "Hello, Piyopiyo"
ポイントは、var delegate: Mochi!
だと思います。(この「delegate」は任意の文字列で大丈夫です。)
改めて、なぜデリゲートが分かりづらいかと言うと。(僕が理解できなかったかと言うと。)
一般的なデリゲートの処理では、このvar delegate: SomeProtocol!
が見えないところに存在しているからです。
例えば、キーボードを押し下げるというデリゲートの簡単なサンプルがあります。
http://qiita.com/mochizukikotaro/items/b35c93866fcc55e201f3
import UIKit
// まず、デリゲートプロトコルを宣言
class ViewController: UIViewController, UITextFieldDelegate {
// テキストフィールドをアウトレット接続して
@IBOutlet var textHoge : UITextField
override func viewDidLoad() {
super.viewDidLoad()
// selfをデリゲートにする
self.textHoge.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// selfをデリゲートにしているので、ここにデリゲートメソッドを書く
func textFieldShouldReturn(textField: UITextField!) -> Bool {
self.view.endEditing(true)
return false
}
}
登場人物は、
- 代理人クラス:ViewController
- 依頼人クラス:UITextField
- プロトコル:UITextFieldDelegate
です。が、ここでUITextField
の中身がどう書かれているかなんて普通見ません。素人は。中身はこうなっていました。
class UITextField : UIControl, UITextInput, UIKeyInput, UITextInputTraits, NSObjectProtocol, NSCoding {
//中略
var delegate: UITextFieldDelegate! // default is nil. weak reference
//中略
}
だから、self.textHoge.delegate = self
と書けば、ちゃんと処理を委任できるんですね。
こんなことは、「べつに普通じゃん。簡単じゃん。」と言われれば、そうなのかもしれないですが、僕としては、
var delegate: UITextFieldDelegate!
という記述を、自分の目で見ないと、どこに書いてあるのか把握できないと、納得感がないのです。
だから、その辺の参考書を読んでも、デリゲートとかプロトコルについて全然分かんないんです。そもそもデリゲートの説明で、プロトコルの説明なかったりしますし。
以上です。
ちなみに、上の例はデリゲート(プロトコル)を使わなくてもできます。
class Hoge2 {
var delegate: Piyo2!
func speak() -> String {
return delegate.say()
}
}
class Piyo2 {
func say() -> String {
return "こんにちは!"
}
}
var hoge2 = Hoge2()
var piyo2 = Piyo2()
hoge2.delegate = piyo2
hoge2.speak()