はじめに
最近PropertyWrapperの概念を知り、使いこなせるとボイラープレートを削減できかなり有用と思ったので記事を書きつつキャッチアップしようと思います。
PropertyWrapperってこんなの
公式ドキュメントでは以下のように説明されています。
A property wrapper adds a layer of separation between code that manages how a property is stored and the code that defines a property. For example, if you have properties that provide thread-safety checks or store their underlying data in a database, you have to write that code on every property. When you use a property wrapper, you write the management code once when you define the wrapper, and then reuse that management code by applying it to multiple properties.
日本語訳
プロパティ ラッパーは、プロパティの格納方法を管理するコードとプロパティを定義するコードの間に分離レイヤーを追加します。たとえば、スレッド セーフティ チェックを提供するプロパティや、基になるデータをデータベースに格納するプロパティがある場合、すべてのプロパティにそのコードを記述する必要があります。プロパティ ラッパーを使用する場合は、ラッパーを定義するときに管理コードを 1 回記述し、その管理コードを複数のプロパティに適用して再利用します。
だいぶ小難しく書いていて、個人的にはピンとこないのですが、簡単な例を見ると腑に落ちるかと思います。
@propertyWrapper
struct NameString {
private var _value: String
init(wrappedValue: String) {
self._value = wrappedValue
self.wrappedValue = wrappedValue
}
var wrappedValue: String {
get { _value + "さん" }
set { _value = newValue }
}
}
struct Human {
@NameString var name: String
init(name: String) {
self.name = name
}
}
上記例では、NameString
というPropertyWrapperを定義し、Human
のname
プロパティに付与しています。
名前なので、必ず末尾に「さん」をつけるようにするという例です。
名前には必ず末尾に「さん」をつけるという仕様があった場合に、いちいち以下の様に名前取得用のコンピューテッドプロパティを用意するといったコードが必要となり、また他のクラスや構造体で名前の表すプロパティを持つことになると、そこでも同じようなコードが必要になります。
こういったコードをボイラープレートといったりしますが、定型的なコードであり毎回同じ様なことを書くのは大変面倒です。
struct Human {
private var _name: String
var name: String {
return _name + "さん"
}
init(name: String) {
_name = name
}
}
ボイラープレートなコードを再利用可能な状態にできることが、PropertyWrapperの良さと言え、公式のドキュメントからも、その様な使用方法のために存在することが読み取れます。
プロパティ ラッパーを使用する場合は、ラッパーを定義するときに管理コードを 1 回記述し、その管理コードを複数のプロパティに適用して再利用します。
おわり
本当に触りだけでしたが、PropertyWrapperの意義を知ることができました。
今回見た限りは簡単な例にとどまっていますが、使い方によっては依存解決のためのコードもPropertyWrapperで省略するなどできたりしそうで実務でもかなり使えるのではと思っています。(swift-dependenciesのライブラリにある@Dependency
多分PropertyWrapperなんだろうなと思うので)
良い使い方見つけたら、また記事にしてみようと思います!