Swiftで使う修飾子の順番（SwiftLintを参照して）

## はじめに

複数の修飾子のつくプロパティを書いているとき、

> :thinking: 「dynamic と public と ＠objc ってどの順番にすべきなんだっけ？」

とか思っていたら、SwiftLintに参考になるものがあったので、まとめます。

## 結論(SwiftLintとしての推奨)

- 推奨順序
    - [override, acl, setterACL, dynamic, mutators, lazy, final, required, convenience, typeMethods, owned]

- 例

```swift
@objc public private(set) dynamic weak var foo: Bar? 
```

```swift
public class Foo: Bar {
   override public final class var foo: String {
       return "bar"
   }
}
```

## SwiftLintのルールの参照先

- [SwiftLintFramework Reference > modifier_order Reference](https://realm.github.io/SwiftLint/modifier_order.html)
- Modifier Order
    - ルールの意味
        - 修飾子の順番は一貫すべき。
    - デフォルトで無効

## 各修飾子の解説

### ACL

- Access Control Level のこと
    - open
    - public
    - internal(デフォルト)
    - fileprivate
    - private

### setterACL

- セッターに対応するゲッターよりも__低い__アクセスレベルを指定して、その変数、プロパティ、または添え字の読み取り/書き込みスコープを制限するために使うもの。
    - fileprivate(set)
    - private(set)
    - internal(set) など。
    - 例

```swift
public struct TrackedString {
    public private(set) var numberOfEdits = 0
    public var value: String = "" {
        didSet {
            numberOfEdits += 1
        }
    }
    public init() {}
}
```

### dynamic

- Objective-Cのランタイムを用いるために使う。@objc を使うときにはdynamicキーワードが必要。
- RealmSwiftを使うときには頻出。

### mutators

- 多分mutating キーワードのこと。
- Swiftでは、特に要求しない限り、プロパティを変更するメソッドを記述できない。
- メソッドの中でプロパティを変更したいときは、mutating キーワードを使ってマークする必要がある。
- 例

```swift
struct Person {
  var name: String
  mutating func makeAnonymous() {
      name = "Anonymous"
	}
}
```

- 呼び出し方

```swift
var person = Person(name: "Ed")
person.makeAnonymous()
```

### lazy

- 参照された時に初めて初期値が設定されるプロパティ。
- 不要なメモリの消費やパフォーマンスの低下を防ぐことができる。
- ただ、もし使うときは気を付ける。いくつか記事見ていると、安易に使うと不具合の元な感じが伝わってきた。

> 便利なlazyですが、
> 初期化タイミングが不明瞭なため思わぬバグを引き起こすことがあります。
>
> 私見ではありますが、
> プロジェクト内での利用タイミングの統一やコメントでの補足等しておく必要はあるかと思います。
>
> 参照先 [【Swift4.1】lazyプロパティの使い所](https://qiita.com/negi0205/items/d367395d5780c915fb1d)

---

> lazyなプロパティは
> 不要なメモリの消費やパフォーマンスの低下を防ぐことができますが
> 使い方を誤ると
> わかりづらい不具合を混ぜてしまう可能性があることがわかりました。
>
> 参照先 [【Swift】Lazyプロパティの使い方に気をつける(ドキュメントの確認は大事)](https://qiita.com/shiz/items/782979bd8a539c9d2291)

### final

- override を防ぐ。

- メソッド、プロパティ、subscript(添え字？)が override されることを防ぐ。 
    - final var
    - final func
    - final class func
    - final subscript
- クラスが継承されることを防ぐ。サブクラス化しようとすると、コンパイル時エラーになる。
    - final class

### required

- クラスの初期化子の前につけて、クラスの全てのサブクラスがその初期化子を実装する必要があることを示す。
- 例

```swift
class SomeClass {
    required init() {
        // initializer implementation goes here
    }
}

class SomeSubclass: SomeClass {
    required init() {
        // subclass implementation of the required initializer goes here
    }
}
```

### convenience

- クラスの初期化子をサポートする。指定した初期化子を呼び出し、その初期化子のパラメーターの一部をデフォルト値に設定できる。
- 例

```swift
class Food {
    var name: String
    init(name: String) {
        self.name = name
    }
    convenience init() {
        self.init(name: "[Unnamed]")
    }
}
```

### typemethod

- 例

```swift
class SomeClass {
    class func someTypeMethod() {
        // type method implementation goes here
    }
}
SomeClass.someTypeMethod()
```

### owned
- unowned
- weak

## 参考サイト

- Swift Document
    - https://swift.org/documentation/