Swiftには、型のメンバー(プロパティ、メソッドなど)および型自体へのアクセスレベルが5つあります。
open — 最大の公開度。モジュールの外部でも継承およびオーバーライドできます。public — モジュールの外部で利用可能ですが、オーバーライド/継承はできません。internal(デフォルト) — モジュール内で利用可能。fileprivate — ファイル内のみにアクセス可能。private — 宣言のスコープ内のみにアクセス可能(extensionもこのスコープ内)。privateは、宣言の外に見えるべきでないロジックに使用します。fileprivateは、同じファイル内でデータを交換する必要がある場合に使用します(たとえば、2つの関連するextension間)。internal — モジュール内で一般公開されるもののデフォルト。public/open — 他のモジュールやフレームワークで使用されるAPI用。open class MyOpenClass {} public class MyPublicClass {} intern class InternalClass {} fileprivate class FilePrivateClass {} private class PrivateClass {}
openはpublicとクラスの定義においてどう違いますか?なぜすべてのpublicクラスが継承に使用できないのですか?
回答:
openは、モジュールの外からオーバーライドおよび継承できるクラス/メソッドにマークします。publicは使用へのアクセスを開きますが、モジュールの外で継承することは許可されません。一方では、実装を望ましくない変更から保護し、他方では必要な拡張ポイントのみを開放します。
public class PublicClass {} open class OpenClass {} // 別のモジュールで: class InheritFromOpen: OpenClass {} // OK class InheritFromPublic: PublicClass {} // エラー!
逸話
あるライブラリでクラスがpublicとしてマークされていて、外部プロジェクトがそれを拡張しようとし、メソッドをオーバーライドしました。プロジェクトはpublicとopenの違いを誤解していたためにコンパイルできず、チームはインターフェースの再設計に余分な1週間を費やしました。
逸話
1つのファイル内で、extensionからprivateプロパティにアクセスしようとしたが、そのプロパティはfileprivateとしてではなく、privateとして宣言されていました。これにより、統合ビルドでのみ見つかったコンパイラエラーが発生しました。
逸話
複数のフレームワークを持つアプリケーションで、すべての型はinternal(デフォルト)としてマークされていました。モジュール間で型を使用する必要が生じたとき、インターフェースが利用できず、publicへの再宣言に十数個の修正が必要で、追加の時間とテストがかかりました。