質問: * goktugyil/EZSwiftExtensions: How Swift standard types and classes were supposed to work. * ReactiveX/RxSwift: Reactive Programming in Swift 上記のようなタイプのクラスにextensionでメソッドを生やすタイプのライブラリについてです。 一度、extensionで生えたメソッドは消せないため、一度コンパイルのタイミングのどこかでimportされるとimportしていないファイルでもその生えたメソッドにアクセスできると思います。これを防ぐことは可能でしょうか? 質問がフワついてしまいそうなので、まとめますと * メソッドを生やすタイプのライブラリはimportすると全ファイル(プロジェクト全体)に影響が出てしまう?(私は出てしまうと認識しており、念の為の確認です) * 出てしまう場合、防ぐ手立てはありますか? * 出てしまうのであれば、どこか一箇所でimportすればよいように思います。その適切な場所とはどこでしょうか?
回答: ### Extensionについて 懸念を検証するために次のようなfileprivateなextensionを作り、2つのViewControllerから生やしたメソッドにアクセスできるか検証してみました。 ``` fileprivate extension UIView { public func test() { print("test") } } ``` 結果 FirstViewController(該当のExtensionを**記述した**ViewController) → アクセスできました。 SecondViewController(該当のExtensionを**記述していない**ViewController) → アクセスできませんでした。 これはextensionのアクセスレベルがfileprivateであるために発生した現象です。 extensionのアクセスレベルを通常のinternal(つまり何も記述しない)にしたところ、両ViewControllerで生やしたメソッドにアクセスできました。 ### ライブラリについて 提示いただいたライブラリの1つであるRxSwiftに含まれるRxCocoaライブラリのソースコードの一部である *UIView+Rx.swift* のソースコードを一部確認しました。 次のような記述でした。 ``` extension Reactive where Base: UIView { /// Bindable sink for `hidden` property. public var isHidden: Binder { return Binder(self.base) { view, hidden in view.isHidden = hidden } } ~~以降は省略~~~ ``` extensionでのアクセス制御はpublicとなっているため、Swiftのソースコード上のどこかでimportするとプロジェクト全体に影響が出るというのは、プロジェクト内部にTarget(いわゆるモジュール)が1つしか無い場合には間違いないと思います。 Targetが複数存在するプロジェクトの場合、自身が所属するTargetではない別Targetに属するクラス情報などを参照することができません(publicでアクセス制御を行っているものは別)。 例としてA TargetではRxSwiftを利用していてimportもしている場合でも、B Targetに属するソースコードではRxSwiftの存在を知らないということになります。 このためA TargetでimportしたRXSwiftをB Targetでimportせず利用することはできません。 そのため、懸念いただいている点はExtensionの仕様によるもの、というより **Swiftという言語のアクセス制御の仕様によるもの** と考えるほうが正しい気がしています。