Swiftで名前空間を利用する


![IMG_1952.JPG](https://qiita-image-store.s3.amazonaws.com/0/16400/655070b6-8aad-919d-e9db-662d045555cf.jpeg "IMG_1952.JPG")

<この記事は[自社のブログにも転載しました](http://curiosity.co.jp/archives/21)>

2014.6.5に[第1回 Swift 勉強会 - ファーストインプレッションを語る会](http://wantedly.connpass.com/event/6751/)がWantedly社が開催されたので参加し、「Swiftは名前空間あるって言ったのに公開されてるドキュメントに書かれてないのどういうことなの」的な相談をしてきました。たしか結論は出なかったのですが、さっき寝てたら思いついたのでそのメモを残しておきます。

（もしご意見などがある場合、[白昼夢のなかでビルドしたみたいな体](http://ch.nicovideo.jp/akiba-cyberspacecowboys/blomaga/ar546266)でコメントを書いていただけるとAppleとのNDA的にセーフっぽい香りがするのではないかと思います）

# 名前空間の定義

ちなみにここでの名前空間の定義は[Wikipedia - 名前空間](http://ja.wikipedia.org/wiki/%E5%90%8D%E5%89%8D%E7%A9%BA%E9%96%93)から

>　ソースコード上で冗長な命名規則を用いなくても名前の衝突が起こらないようにし、しかもそれを容易に記述できるようにするためだけの概念

とします。

# 名前空間の利用法

まず公開されたドキュメントから2つのやり方が考えられると思います

- Nested Typesを利用する方法
- モジュールを利用する方法


## Nested Typesを利用する方法について

Nested Typesは単純にクラスの中にクラス（もしくは構造体）を用意するだけです。これによりドット記法でアクセスすることは出来ます。ただそれは冗長な命名規則とそれほど変わらないやり方ではないかと思います。

例えばUITableViewとUITableViewCellを継承したTableViewとTableViewCellが必要になった時、これらを名前の衝突が起こらないようにするためMyObjectクラスという命名用クラスを作るのであれば次のようになります。


```swift
import UIKit
//ビルドした結果から書いているわけじゃないのでビルドできるかどうかは分かりません...
class MyObject{

    class UITableView : UIKit.UITableView {
    }

    class UITableViewCell : UIKit.UITableViewCell{
    }
}
```

名前の衝突を避けるためのクラスというのは実動作上の必要性が乏しく、なんだか結局冗長な命名規則の上に成り立っているように思えます。少なくともモダンじゃないなって感じですね。


## モジュールを利用する方法について

モジュールとはUIKitやFoundationのことです。ドキュメントによるとimportを使って呼び出すようですね。

```swift
import module.submodule
```


また、[Appleの公開しているswiftのページ](https://developer.apple.com/library/prerelease/ios/documentation/swift/conceptual/swift_programming_language/Declarations.html)から、モジュールのスコープの項目には下記のように書いてありました

> The module scope defines the code that’s visible to other code in Swift source files that are part of the same module. 

正直ピンと来ないんですが、Swiftソースコードではモジュールという概念の中にあるっぽいことだけは分かります。つまり私が適当に書いたコードは何かのモジュールの中にあるということで、これはUIKitのモジュールとは区別されるのではないかな、という気になります。

なのでUITableViewCellというクラスを自前でも作りたくなった場合（実際は作りたくなったりすることはなく、たまたま同じクラス名になったら困るという話ですが）下記のように書いてみても実際は衝突することはありません。

```swift
import UIKit
//ビルドした結果から書いているわけじゃないのでビルドできるかどうかは分かりません...
class UITableViewCell : UIKit.UITableViewCell {
    
}
```

ちなみに、これを書いたあとに「namespace swift module」でググったらStackOverflowがヒットして、Foundation.NSLogで説明してる人がいますね
http://stackoverflow.com/a/24032860


### 他のライブラリとは衝突しないのか

ここまでの予想が正しいなら下記のような条件と結果になるはずです

- Swiftコードからビルドしstatic link libraryにしたものはそのビルドした際のモジュールになっている気がします
- Cocoapodsで取得したSwiftのコードはひとつのワークスペース内で別プロジェクトとしてビルドされるのでこれも問題なさそうです
- Cocoapodsで複数のObjCのコードを取得しビルドした場合、これはモジュールの概念がないので同じクラス名なら衝突すると思います
- Swiftソースコードのみプロジェクトにコピーしてきた場合。同じモジュール内になるので同じクラス名だと衝突すると思います

# まとめ

Swiftでは名前空間は暗黙的に利用されていてAppleのクラス名と衝突することはないですし、他のプロジェクトのSwfitで書かれたコードを読み込んだ場合にもクラス名が衝突することはないということです。

## 参考: AppleのSwift設計者のTweet

<blockquote class="twitter-tweet" lang="ja"><p>Namespacing is implicit in swift, all classes (etc) are implicitly scoped by the module (Xcode target) they are in. no class prefixes needed</p>&mdash; Chris Lattner (@clattner_llvm) <a href="https://twitter.com/clattner_llvm/statuses/474730716941385729">2014, 6月 6</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

# 最後に

勉強会の開催を行ってくださったWantedly社は[Swiftなら誰にも負けないiOSエンジニア・ウォンテッド！！](https://www.wantedly.com/projects/7755)しているそうです。


ちなみに「もうSwift飽きたわー、俺が一番最初に飽きたわー」という人ウォンテッド！！って募集するようなところが出てきたら今のうちだけ注目されると思いますのでぜひどこかやってみたらいかがでしょうか。