Swiftのextensionsは、標準型(例えば、String、Array)や独自の型を継承せずに元のソースコードを変更することなく拡張する手段として登場しました。これにより、新しいメソッド、計算プロパティ、プロトコルへの適合を追加し、コードの可読性と一貫したアーキテクチャを維持できます。
問題は、extensionsの過剰または無秩序な使用により発生します:型の元の動作を失いやすく、名前の衝突が生じ、特に大規模プロジェクトや外部ライブラリを使用する際に、何がどこから来ているのかを追跡するのが難しくなります。
解決策は、明確な構造を持つこと、extensionsを意味的なグループに整理すること、明示的なドキュメントを作成すること、既存の名前との衝突を回避すること、必要に応じて作用範囲を制限すること(例えば、fileprivateまたはinternalを使用すること)です。
コードの例:
extension String { var isEmail: Bool { return self.contains("@") && self.contains(".") } func trimmed() -> String { return trimmingCharacters(in: .whitespacesAndNewlines) } }
主な特徴:
extensionを介してstored propertyを追加できますか?
いいえ、extensionでは計算プロパティとメソッドのみを追加できます。stored propertiesをextensionで追加することはできません。試してみると、コンパイラはすぐにエラーを出します。
異なるファイル内の異なるextensionで同じ名前のメソッドを宣言した場合、どうなりますか?
名前の衝突が発生し、Swiftはどのメソッドを呼び出すべきかを判断できず、エラーはコンパイル時に発生します。
extensionsは、extension内でのみ見えるprivateメソッドを実装できますか?
はい。privateでメソッドを宣言すれば、そのメソッドはextension自身と、それが宣言されたファイル内でのみ見えます(fileprivateを使用する場合)。
extension Int { private func isEvenInternal() -> Bool { return self % 2 == 0 } func publicCheckEven() -> Bool { return isEvenInternal() } }
** ネガティブなケース
大規模プロジェクトでStringにextensionを使用してメール検証からJSONパースまでのメソッドを追加しています。1年後、誰もがどこから何が来ているのか理解できなくなります:メソッド名が衝突し、誰かが新しい関数を追加し古い関数を知らずに、依存性の動作を壊します。
利点:
欠点:
** ポジティブなケース
チームは論理グループのためにextensionsを使用しています:検証のための別のextension、フォーマッティング用の別のextension、内部にプライベートなヘルパーを含む。すべてのメソッドは文書化されており、新しいメソッドの使用については議論され、コードレビューがあります。
利点:
欠点: