【プログラミング初心者】Swift基礎~アクセス修飾子~

#はじめに
今回はオブジェクト指向の考え方の１つであるカプセル化を実現するためのアクセス修飾子の使い方について紹介します。
カプセル化がどういうものかは[こちら](https://qiita.com/euJcIKfcqwnzDui/items/3a442bdee2996654dd97#%E3%82%AB%E3%83%97%E3%82%BB%E3%83%AB%E5%8C%96)で紹介しているので参照してください。

#アクセス修飾子
**アクセス修飾子**はそのプロパティもしくはメソッドを外から呼べるかどうかの権限を表します。
これは定義の頭に付けるもので構文は以下となります。

```swift:アクセス修飾子構文
// プロパティの場合
アクセス修飾子 var 変数: 型

// メソッドの場合
アクセス修飾子 func メソッド名() {

}
```
見ればわかるようにいつもの定義の仕方の頭にアクセス修飾子を付けるだけですね。

Swiftのアクセス修飾子は以下の５種類があります。
上から順に制約はゆるくなります。

|アクセス修飾子  |概要                                          |
|-------------|---------------------------------------------|
|private      |クラス内からしかアクセスできない                     |
|fileprivate  |同じファイル内からしかアクセスできない                 |
|internal     |同じモジュール内からはどこからでもアクセスできる          |
|public       |他のモジュールからもアクセスできるがオーバーライドできない  |
|open         |他のモジュールからもアクセスでき、オーバーライドできる      |

よく使うのは`private`と`internal`になるかと思います。
この２つについて具体的な実装を紹介します。

##private
最も厳しいアクセス修飾子でクラス内でしか呼び出せないプロパティ、メソッドに付けます。

```swift
class MyClass {
    private var privateProperty = 0
    
    private func privateMethod() {
        print("privateMethod")
    }
    
    func testMethod() {
        self.privateMethod() // OK
        let tmp = self.privateProperty // OK
    }
}

let myClass = MyClass()
myClass.privateMethod()  // NG
let tmp = myClass.privateProperty // NG
```
`noPrivateMethod()`での呼び出しのようにクラス内で扱う時は特に気にする必要はありません。
クラスの外から呼び出そうとすると
・*'privateMethod' is inaccessible due to 'private' protection level*
・*'privateProperty' is inaccessible due to 'private' protection level*
というように怒られます。
※そもそも`private`で指定したメソッド、プロパティは補完候補にも挙がってきません。

##internal
「同じモジュール内からはどこからでもアクセスできる」と説明しています。
モジュールとありますが今はそれほど意識しなくても構いません。
アプリ内であればどこからでもアクセスできるととりあえずは覚えてください。

またアクセス修飾子なしでメソッド、プロパティを定義すると`internal`として扱われます。
そのため自分で`internal`と指定することはあまりないかと思います。

以下実装例です。

```swift
class MyClass {
    internal var privateProperty1 = 0
    var privateProperty2 = 0
    
    internal func internalMethod1() {
        print("internalMethod1")
    }
    
    func internalMethod2() {
        print("internalMethod1")
    }
    
    func testMethod() {
        self.internalMethod1() // OK
        self.internalMethod2() // OK
        let tmp1 = self.privateProperty1 // OK
        let tmp2 = self.privateProperty2 // OK
    }
}

let myClass = MyClass()
myClass.internalMethod1() // OK
myClass.internalMethod2() // OK
let tmp1 = myClass.privateProperty1 // OK
let tmp2 = myClass.privateProperty2 // OK
```
このように外から参照できるものは今まで通り何も付けない or `internal`を付けると覚えましょう。

##private(set)
プロパティに関しては外から変えられたくないが参照はできるというものもあります。
**readonlyプロパティ**などと言ったりします。
このときのアクセス修飾子は**private(set)**を使用します。

以下実装例です。

```swift
class MyClass {
    private(set) var readOnlyProperty = 0
    
    func testMethod() {
        let tmp = self.readOnlyProperty // OK
        self.readOnlyProperty = 1 // OK
    }
}

let myClass = MyClass()
let tmp = myClass.readOnlyProperty // OK
myClass.readOnlyProperty = 1 // NG
```
`myClass.readOnlyProperty = 1`とすると
*Cannot assign to property: 'readOnlyProperty' setter is inaccessible*
と怒られます。

#最後に
今回はカプセル化を実現するためのアクセス修飾子について紹介しました。
それほど難しい内容ではないかなと思うのでこの機会に覚えておきましょう。
もちろんどれを公開してどれを非公開にするかの判断には多少の経験がいるかとは思いますが。

今回の内容は以上です。
本記事とは別でプログラミング未経験からiOSアプリ開発が行えるようになることを目的とした記事を連載しています。
連載は以下にまとめていますのでそちらも是非もご覧ください。
http://naoyalog.com/