cockscomblog?

cockscomb on hatena blog

Swift 3 の private と fileprivate

おはようございます。バットマンです。PlayStation VR でバットマン:アーカム VRを遊んだところ、現実とゲームの区別がつかなくなりました。ヘッドセットを外した後も、手がオブジェクトにめり込むんじゃないかと錯覚するようになった。

ところで Swift ピープルの皆さんも、最近はプロジェクトを Swift 3 にマイグレーションしたりして暮らしていらっしゃることかと思います。御多分に洩れず、僕もマイグレーションして暮らしています。いろいろコツも掴めてきたところではありますが、それはともかく、privatefileprivate について割り切れないものを感じている昨今です。

privatefileprivate

SE-0025 Scoped Access Level で Swift 3 に導入された privatefileprivate は、Swift 2 までの private はファイル内で可視であるというのを fileprivate とした上で、定義内で可視であるという private を新たに導入したものである。これによって private の意味が他の言語などと揃い、一方で Swift の extension の仕組みと親和的な fileprivate が残された、ということになる。

Swift 2 から Swift 3 へ自動マイグレータを適用すると、Swift 2 の private はすべて Swift 3 の fileprivate へ書き換えられる。これらは全く同じなので正しい。しかし fileprivate は長ったらしいので、可能なら private へ置き換えていきたい。ひとまずすべて private にしてみて、コンパイルが通るように fileprivate へ戻す、といった方法で可能な限り private にしていく。extension で何らかの protocol に準拠していて、そのために stored property を fileprivate にしなければならない、というようなことがある。

そういうことをしていると、いまこの privatefileprivate の差が、いったい何の意味を持っているのかだんだん分からなくなる。このコードを読むとき、privatefileprivate の違いをどういう風に解釈したらよいのか。

同一ファイル上で extension によって実装を分けている場合、privatefileprivate を明確に分離できない。同一ファイル上の別な classstruct であれば、privatefileprivate の違いが役に立つかもしれない。しかしそれは、そもそも別なファイルに分けておけばよかったのかもしれない。

ということで、privatefileprivate の分離自体は正しいのだけど、実際にはうまく使い分けることが難しく、一筋縄にはいかない。

他方で internalpublicopen は明々白々に使い分けられて便利。