Swiftのプロパティ監視willset/didset
こんにちは!かずきです。 今回はSwiftの特徴的機能の一つ、プロパティ監視のdidset/willsetについて書いていきたいと思います。 前回に続き、Swift入門者向けの記事です。
プロパティとは
private var hoge: Int = 0 public var Hoge: Int{ set{ self.hoge = newValue } get{ return self.hoge } }
読み書きそれぞれ別の範囲でのアクセス制限を掛けたい場合などのアクセス制御に使用するものです。
上のようにsetで囲んで値を設定するsetter
とget囲んで値を渡すgetter
の2種類があります。
class HogeHoge { private var hoge: Int = 0 public var Hoge: Int{ get{ return self.hoge } } }
このようなプロパティを持つクラスがあるとして、次のようにアクセスすると。。。
let hogehoge = HogeHoge() print("\(hogehoge.Hoge)") // "0" // エラー hogehoge.Hoge = 1
値の取得には成功しますが、代入は失敗してしまいます。
このように外部からは取得しか出来ず、書き換えさせない場合や複数の変数の計算結果などを返したい場合によく利用されます。
プロパティとプロパティ監視の違い
プロパティは変数のアクセス制御
などに使用するのに対し、プロパティ監視は変数の変更を監視
するものになります。
なぜ変数の監視
なのにプロパティ監視
なのかと言うと、Swiftでは変数もプロパティの1種
として扱われているからです。
先程説明したプロパティと変数としてのプロパティの違いは次に説明します。
2種類のプロパティ
Swiftにコンピューテッドプロパティ
とストアドプロパティ
の2種類のプロパティがあります。
コンピューテッドプロパティ
先ほど紹介したものはこちらです。
プロパティそのものには値を格納出来ません
。
よくプロパティ
と呼ばれるものはこちらになります。ストアドプロパティ
一般的に変数
と呼ばれるのもです。
getter
setter
は利用出来ませんが、 こちらのプロパティには値を格納出来ます
。
Swiftではこのように2種類のプロパティとして扱われています。
説明はしましたが、Swiftでは変数もプロパティの一種くらいの認識で大丈夫だと思います。
プロパティ監視(willset / didset)
プロパティ監視は先程説明した通り変数の変更を監視する
ものです。
willset
・・・変数の値の変更前
に通知されるdidset
・・・変数の値の変更後
に通知される
var hoge:Int = 0 { willSet(newValue){ hoge = 0 // 値は変わらない } didSet(oldValue){ if(hoge < oldValue) { print("元の値より小さい値は代入できません。\(oldValue) -> \(hoge)") hoge = oldValue // 値は変わる(この場合willset / didsetには通知されない) } } }
willset
で自身の変数に代入しても値は変化しません
が、didset
内で代入した場合は値が変化します
。
didset
内で自身の変数を変化させた場合willset
didset
には通知されません。
プロパティ監視の使い所
先程の説明で処理の場合、setter
でも同じ内容の事をする事が出来ます。
主なプロパティ監視の使いどころしては、値が変化された場合に特定のメソッドを呼ぶ
イベントで通知する
などです。
まとめ
ここまで説明してきましたが、基本的にwillset / didset
で出来る処理はgetter / setter
でも出来ます。
ですが。。。
読み書きそれぞれ
別の範囲でのアクセス制限
を掛けたい場合はgetter
setter
で処理を記述する。値が変更された場合に処理を行いたい場合
willset
didset
で処理を記述する。
このような使い分けで利用する事により、
変数(ストアドプロパティ)プロパティ(コンピューテッドプロパティ)両方にアクセス可能な場所で
setterに必要な処理
を書いているので変数に代入
してしまって正しい処理がされないなどのリスクを回避する事が出来ます。
他にも使い分け方があれば是非教えて下さい!