Swift

[Swift] Property のベストプラクティスを考える

More than 3 years have passed since last update.


これはなに

Swift には Property という機能があります。それにより setter/getter が手軽に書けるようになりました。

どのようにしたら可読性に優れ、簡潔になるかを考えてみたという記事です。


Property とは

公式ドキュメント:https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html

Swift は相変わらず公式ドキュメントが読みやすくてよいですね。

Objective-C でも property はありましたね。プロパティ宣言をよくしていたと思います。


Objective-C

@interface Hoge: NSObject {

NSString *_string = @"";
}
@property (nonatomic, strong, getter = getString, setter = setString:) NSString *string;
@end

@implementation Hoge: NSObject
- (NSString*) getString {
return _string;
}

- (void) setString: (NSString*) newValue {
_string = newValue;
}
@end


まあここまで明示的に書くことはなかなかないですが、Objective-C ではプロパティ宣言で getter/setter を指定していました。

読み取り専用の場合は readonly をつけたりしましたね。

全く同じものは、Swift では以下のように書くことができます。


Swift

class Hoge {

var _string = ""
var string: String {
get {
return _string
}
set {
_string = newValue
}
}
}

まあこれだと、「なんだかカッコつけたようになったな」という感想があると思います。


それって、これで済むよね


Swift

class Hoge {

var string = ""
}

Objective-C のプロパティ宣言で getter/setter の記述を省略できるのと同じように、 getter/setter で代入、取り出し以外の操作をしないならば プロパティを使う必要はないと思います。


プロパティを使いたい場面


  • setter にもう一手間加えたい

例えば、代入されたらそれを NSUserDefaults に保存したいとき。


Swift

class Hoge {

var _string = ""
var string: String {
get {
return _string
}
set {
_string = newValue
NSUserDefaults.standardUserDefaults().setObject(newValue, forKey: "string")
}
}
}

おお、これだとわざわざ setter を書いた意味がありそう。


でもそれって、これで済むよね(二回目)


Swift

class Hoge {

var string: String = "" {
didSet {
NSUserDefaults.standardUserDefaults().setObject(string, forKey: "string")
}
}
}

Property には、 didSet, willSet というセット直後・直前に呼ばれる場所を定義することができます。

だから、 setter に一手間ならば didSet, willSet でやればいいですね。


getter/setter を本当に使いたいケース


readonly な変数


Swift

class Hoge {

var string: String {
get {
return "hoge"
}
}
}

このように、getter のみを記述すればその変数は readonly となります。

この記法だとカッコが多いので、以下のように省略できます。また GitHubのスタイルガイド で可読性とコード行数の観点から省略形が推奨されています。


Swift

class Hoge {

var string: String {
return "hoge"
}
}


他の変数と組み合わせて使う


Swift

class Rect {

var width: Float = 0
var height: Float = 0
var area: Float {
return width * height
}
}

この場合は area はクラスの他の2変数から常にかけ算の結果を返します。また、readonly なので安心です。


まとめ

Swift の Property は Objective-C のそれと比べ読みやすく、わかりやすくなっていると感じます。

また複数の方法で同じ処理を実現することができます。

なので、いつも同じ書き方、ではなく状況に応じて最も読みやすく、簡潔な書き方を心がけていきたいものです。