Swiftクラスのプロパティの初期化処理をどうにかしたい


```swift:Xcode7.1.1
➜  ~  swift --version
Apple Swift version 2.1 (swiftlang-700.1.101.6 clang-700.1.76)
Target: x86_64-apple-darwin15.0.0
```

##動機
プロパティ名が無駄に長い場合、入力補完があるとはいえ、いちいち`self.longNameProperty.hoge = fuga`と書くのが面倒臭い。
短いプロパティ名をつけても、プロパティのプロパティが短い名前とは限らない。

```swift
self.longNameProperty = UIView(frame: CGRectMake(0,0,100,100))
self.longNameProperty.backgroundColor = UIColor.whiteColor()
self.longNameProperty.autoresizesSubviews = false
self.longNameProperty.layer.cornerRadius = 8
self.longNameProperty.layer.shadowColor = UIColor.blackColor().CGColor
self.longNameProperty.layer.borderColor = UIColor.redColor().CGColor
self.longNameProperty.layer.borderWidth = 5
```

短い名前の変数を作って、最後に代入することもできるが、複数のプロパティを設定しないといけない場合、同じスコープに短い似たような名前の変数がたくさんできてしまうのが嫌。

```swift
let v1 = UIView(frame: CGRectMake(0,0,100,100))
v1.backgroundColor = UIColor.whiteColor()
v1.autoresizesSubviews = false
v1.layer.cornerRadius = 8
v1.layer.shadowColor = UIColor.blackColor().CGColor
v1.layer.borderColor = UIColor.redColor().CGColor
v1.layer.borderWidth = 5
self.longNameProperty = v1
let v2 //...
let v3 //...
//同じスコープにv1, v2, ..みたいなのがたくさん出るのが嫌。
```

また、同じような初期化をするなら、関数化すれば良いだけだが、各プロパティで全く異なる初期化処理をする場合は関数化する意味がない。

##解決案
###実装方法(ジェネリクス版)
`NSObject`を拡張してスコープを作るメソッドを生やしてみる。

```swift:NSObject+Ext
extension NSObject {
    func scope<T: NSObject>(block: (T)->Void) -> Self {
        if let obj = self as? T {
            block(obj)
        }
        return self
    }
}
```

###使用方法
長いプロパティ名を書く数が減り、短い変数名の氾濫を抑えられる。
インデントがついて読みやすい。

```swift
self.longNameProperty = UIView().scope { (v: UIView) in
    v.frame = CGRectMake(0, 0, 100, 100)
    v.backgroundColor = UIColor.whiteColor()
    v.autoresizesSubviews = false
    v.layer.scope { (l: CALayer) in
        l.cornerRadius = 8
        l.shadowColor = UIColor.blackColor().CGColor
        l.borderColor = UIColor.redColor().CGColor
        l.borderWidth = 5
    }
}
```

###問題点等

- パフォーマンスは考えてない
- インデントなしの方が見やすい？

私はインデントがついている方が読みやすいと思いますが、一番初めの例のように左詰めで揃っている方が読みやすいという人もいるでしょう。 **万人ウケするとは思ってません。**

- クロージャの引数の型を指定しなければならない

本当は次のようにしたかったのですが、ジェネリクスに`Self`は使えないし...
良い方法があれば教えてください。->*プロトコルエクステンションを使う。*

```swift
self.longNameProperty = UIView().scope { v in
//...
}
```

- `NSObject`でしか使えない

`AnyObject`や`Any`は拡張できないので、`NSObject`を継承していないクラスや構造体には使用できない。

##プロトコルエクステンションを使う方法(追記)
[tom-u](http://qiita.com/tom-u)さんに教えていただいた方法。
プロトコルだと`Self`を引数の型にできるので、プロトコルエクステンションでscopeメソッドを作る。

```swift
protocol  ScopeProtocol {}
extension ScopeProtocol {
    func scope(block: (Self) -> Void) -> Self {
         block(self)
         return self
    }
}
extension NSObject: ScopeProtocol {}
```
これで、型を指定せずに次のように書けます。

```swift
self.longNameProperty = UIView().scope { v in
    v.frame = CGRectMake(0, 0, 100, 100)
    //...
}
```

##doブロックを使う方法 (追記)
コメント欄で[kishikawakatsumi](http://qiita.com/kishikawakatsumi)さんに教えていただきました。
doとcatchがセットだと思っていましたが、doブロックは単体で使えます。
こっちの方が良いかもしれません。

```swift
do {
    let v = UIView(frame: CGRectMake(0, 0, 100, 100))
    v.backgroundColor = UIColor.whiteColor()
    v.autoresizesSubviews = false
    do {
        let l = v.layer
        l.cornerRadius = 8
        l.shadowColor = UIColor.blackColor().CGColor
        l.borderColor = UIColor.redColor().CGColor
        l.borderWidth = 5
    }
    self.longNameProperty = v
}
```

##closureのみを使う方法(追記)
[su_k](http://qiita.com/su_k)さんに教えていただいた方法。
closureを作って直ちに使う。protocol extensionとか書かなくてもいい。

```swift
self.longPropertyName = {
    let v = UIView(frame: CGRectMake(0, 0, 100, 100))
    v.backgroundColor = UIColor.whiteColor()
    v.autoresizesSubviews = false
    _ = { // _ = がない場合はdoを使えと言ってくる
        let l = v.layer
        l.cornerRadius = 8
        l.shadowColor = UIColor.blackColor().CGColor
        l.borderColor = UIColor.redColor().CGColor
        l.borderWidth = 5
        }()
    return v
    }()
```
*layerのところは素直にdoで良いでしょう。*
*control+iした時の"}"の位置がscope(){}の場合と違いますね。*

##各方法の特徴(追記)
最終的にはパフォーマンスとXcodeのインデンテーション(範囲指定してctrl+i)した時の読みやすさと手間でどれを使うか決めれば良いと思います。読みやすさは個人差があると思いますが...

- scope(): 

拡張が必要な分、少しだけ手間。propertyが既に別な場所で作られて設定だけをしたい場合にも同じような形式で記述できるのがいい。*見やすい?*

- do:

拡張必要なし。ベンチマークしたわけではないですが、パフォーマンスが良いはず。

- closureのみ:

拡張必要なし。*doより見やすい?*