Skip to content

アクセスコントロール

Swiftでコードの可視性を宣言、ファイル、モジュールで管理します。

概要

アクセス制御は、他のソースファイルやモジュールのコードからコードの一部へのアクセスを制限します。この機能によってコードの実装の詳細を隠し、そのコードにアクセスして使用できる優先的なインターフェースを指定できます。

個々の型(クラス、構造体、列挙型)や、それらの型に属するプロパティ、メソッド、イニシャライザ、サブスクリプトに特定のアクセスレベルを割り当てることができます。プロトコルは特定のコンテキストに制限することができ、グローバル定数、変数、関数も同様です。

Note
以下のセクションでは、簡潔にするために、アクセス制御を適用できるコードのさまざまな側面(プロパティ、型、関数など)を「エンティティ」と呼びます。

モジュール、ソースファイル、パッケージ

Swiftのアクセス制御モデルは、モジュール、ソースファイル、パッケージの概念に基づいています。

モジュール

モジュールは、コード配布の単一単位です - 単一のユニットとしてビルドおよび出荷され、Swiftのimportキーワードで別のモジュールによってインポートできるフレームワークまたはアプリケーションです。

ソースファイル

ソースファイルは、モジュール内の単一のSwiftソースコードファイルです(実質的には、アプリまたはフレームワーク内の単一ファイル)。個々の型を別々のソースファイルに定義することが一般的ですが、単一のソースファイルに複数の型、関数などの定義を含めることができます。

パッケージ

パッケージは、単一のユニットとして開発するモジュールのグループです。パッケージを構成するモジュールは、Swiftソースコードの一部としてではなく、使用しているビルドシステムの設定の一部として定義します。たとえば、Swift Package Managerを使用してコードをビルドする場合、Package.swiftファイルでPackageDescriptionモジュールのAPIを使用してパッケージを定義します。Xcodeを使用する場合、Package Access Identifierビルド設定でパッケージ名を指定します。

アクセスレベル

Swiftは、コード内のエンティティに対して6つの異なるアクセスレベルを提供します。これらのアクセスレベルは、エンティティが定義されているソースファイル、そのソースファイルが属するモジュール、およびそのモジュールが属するパッケージに対して相対的です。

  • openアクセスとpublicアクセスは、定義モジュールの任意のソースファイル内、および定義モジュールをインポートする別のモジュールのソースファイル内でエンティティを使用できるようにします。通常、フレームワークの公開インターフェースを指定する際にopenまたはpublicアクセスを使用します。openアクセスとpublicアクセスの違いは、後述のサブクラス化で説明します。
  • packageアクセスは、定義パッケージの任意のソースファイル内でエンティティを使用できるようにしますが、そのパッケージ外のソースファイルでは使用できません。通常、複数のモジュールに構造化されたアプリやフレームワーク内でpackageアクセスを使用します。
  • internalアクセスは、定義モジュールの任意のソースファイル内でエンティティを使用できるようにしますが、そのモジュール外のソースファイルでは使用できません。通常、アプリやフレームワークの内部構造を定義する際にinternalアクセスを使用します。
  • file-privateアクセスは、エンティティの使用を定義ソースファイル内に制限します。特定の機能の実装の詳細を隠すためにfile-privateアクセスを使用します。
  • privateアクセスは、エンティティの使用を囲む宣言および同じファイル内のその宣言の拡張に制限します。特定の機能の実装の詳細を隠すためにprivateアクセスを使用します。

openアクセスは最も高い(最も制限の少ない)アクセスレベルであり、privateアクセスは最も低い(最も制限の多い)アクセスレベルです。

openアクセスはクラスおよびクラスメンバーにのみ適用され、モジュール外のコードがサブクラス化およびオーバーライドできる点でpublicアクセスとは異なります。クラスをopenとしてマークすることは、他のモジュールのコードがそのクラスをスーパークラスとして使用する影響を考慮し、そのクラスのコードを適切に設計したことを明示的に示します。

アクセスレベルの指針

Swiftのアクセスレベルは、全体的な指針に従います: あるエンティティは、より低い(より制限の多い)アクセスレベルを持つ別のエンティティに基づいて定義することはできません。

たとえば:

  • public変数は、internalfile-private、またはprivate型を持つように定義することはできません。なぜなら、その型はpublic変数が使用されるすべての場所で利用可能であるとは限らないからです。
  • 関数は、そのパラメータ型および戻り型よりも高いアクセスレベルを持つことはできません。なぜなら、その関数は、その構成要素の型が周囲のコードで利用できない状況で使用される可能性があるからです。

この指針の具体的な意味は、言語のさまざまな側面に対して以下で詳しく説明します。

デフォルトのアクセスレベル

コード内のすべてのエンティティ(この章で後述するいくつかの特定の例外を除く)は、明示的なアクセスレベルを指定しない場合、デフォルトのアクセスレベルとしてinternalを持ちます。そのため、多くの場合、コード内で明示的なアクセスレベルを指定する必要はありません。

シングルターゲットアプリのアクセスレベル

シンプルなシングルターゲットアプリを書くとき、アプリ内のコードは通常、アプリ内で自己完結しており、アプリのモジュール外で利用可能にする必要はありません。デフォルトのアクセスレベルであるinternalは、この要件にすでに一致しています。したがって、カスタムアクセスレベルを指定する必要はありません。ただし、アプリのモジュール内の他のコードから実装の詳細を隠すために、コードの一部をfile-privateまたはprivateとしてマークすることはできます。

フレームワークのアクセスレベル

フレームワークを開発する際には、そのフレームワークの公開インターフェースをopenまたはpublicとしてマークし、他のモジュール(フレームワークをインポートするアプリなど)から表示およびアクセスできるようにします。この公開インターフェースは、フレームワークのアプリケーションプログラミングインターフェース(API)です。

Note
フレームワークの内部実装の詳細は、デフォルトのアクセスレベルであるinternalを使用するか、他のフレームワークの内部コードから隠すためにprivateまたはfile-privateとしてマークできます。エンティティをopenまたはpublicとしてマークする必要があるのは、そのエンティティをフレームワークのAPIの一部にしたい場合だけです。

ユニットテストターゲットのアクセスレベル

ユニットテストターゲットを持つアプリを書くとき、アプリ内のコードはそのモジュールに対して利用可能にする必要があります。デフォルトでは、openまたはpublicとしてマークされたエンティティのみが他のモジュールからアクセス可能です。ただし、ユニットテストターゲットは、製品モジュールのインポート宣言に@testable属性をマークし、その製品モジュールをテスト有効でコンパイルすることで、任意のinternalエンティティにアクセスできます。

アクセス制御の構文

エンティティの宣言の先頭にopenpublicinternalfileprivate、またはprivate修飾子を配置して、エンティティのアクセスレベルを定義します。

swift
open class SomeOpenClass {}
public class SomePublicClass {}
internal class SomeInternalClass {}
fileprivate class SomeFilePrivateClass {}
private class SomePrivateClass {}

open var someOpenVariable = 0
public var somePublicVariable = 0
internal let someInternalConstant = 0
fileprivate func someFilePrivateFunction() {}
private func somePrivateFunction() {}

明示的に指定されていない場合、デフォルトのアクセスレベルはinternalです。これは、SomeInternalClassおよびsomeInternalConstantが明示的なアクセスレベル修飾子なしで書かれても、アクセスレベルがinternalであることを意味します。

swift
class SomeInternalClass {}              // 暗黙的にinternal
let someInternalConstant = 0            // 暗黙的にinternal

カスタム型

カスタム型の明示的なアクセスレベルを指定する場合は、その型を定義する時点で行います。新しい型は、そのアクセスレベルが許す限り、どこでも使用できます。たとえば、ファイルプライベートクラスを定義する場合、そのクラスはファイルプライベートクラスが定義されているソースファイル内でのみ、プロパティの型、関数のパラメータ、または戻り型として使用できます。

型のアクセス制御レベルは、その型のメンバー(プロパティ、メソッド、イニシャライザ、サブスクリプト)のデフォルトのアクセスレベルにも影響します。型のアクセスレベルをprivateまたはfile-privateとして定義すると、そのメンバーのデフォルトのアクセスレベルもprivateまたはfile-privateになります。型のアクセスレベルをinternalまたはpublicとして定義する(または明示的にアクセスレベルを指定せずにデフォルトのアクセスレベルであるinternalを使用する)場合、その型のメンバーのデフォルトのアクセスレベルはinternalになります。

Important
public型はデフォルトでinternalメンバーを持ちます。publicメンバーにしたい場合は、明示的にマークする必要があります。この要件は、型の公開APIが公開することを選択したものであり、型の内部動作を誤って公開APIとして提示することを避けるためです。

swift
public class SomePublicClass {                   // 明示的にpublicクラス
    public var somePublicProperty = 0            // 明示的にpublicクラスメンバー
    var someInternalProperty = 0                 // 暗黙的にinternalクラスメンバー
    fileprivate func someFilePrivateMethod() {}  // 明示的にfile-privateクラスメンバー
    private func somePrivateMethod() {}          // 明示的にprivateクラスメンバー
}

class SomeInternalClass {                        // 暗黙的にinternalクラス
    var someInternalProperty = 0                 // 暗黙的にinternalクラスメンバー
    fileprivate func someFilePrivateMethod() {}  // 明示的にfile-privateクラスメンバー
    private func somePrivateMethod() {}          // 明示的にprivateクラスメンバー
}

fileprivate class SomeFilePrivateClass {         // 明示的にfile-privateクラス
    func someFilePrivateMethod() {}              // 暗黙的にfile-privateクラスメンバー
    private func somePrivateMethod() {}          // 明示的にprivateクラスメンバー
}

private class SomePrivateClass {                 // 明示的にprivateクラス
    func somePrivateMethod() {}                  // 暗黙的にprivateクラスメンバー
}

タプル型

タプル型のアクセスレベルは、そのタプルに使用されるすべての型の中で最も制限の厳しいアクセスレベルです。たとえば、internalアクセスとprivateアクセスの2つの異なる型からタプルを構成する場合、その複合タプル型のアクセスレベルはprivateになります。

Note
タプル型は、クラス、構造体、列挙型、関数のように独立した定義を持ちません。タプル型のアクセスレベルは、タプル型を構成する型から自動的に決定され、明示的に指定することはできません。

関数型

関数型のアクセスレベルは、関数のパラメータ型および戻り型の中で最も制限の厳しいアクセスレベルとして計算されます。関数の計算されたアクセスレベルがコンテキストのデフォルトと一致しない場合は、関数の定義の一部としてアクセスレベルを明示的に指定する必要があります。

以下の例では、特定のアクセスレベル修飾子を提供せずに、someFunction()というグローバル関数を定義しています。この関数はデフォルトのアクセスレベルであるinternalを持つと予想されるかもしれませんが、実際にはそうではありません。以下のように書かれたsomeFunction()はコンパイルされません。

swift
func someFunction() -> (SomeInternalClass, SomePrivateClass) {
    // 関数の実装がここに入ります
}

関数の戻り型は、上記のカスタム型で定義された2つのクラスから構成されるタプル型です。これらのクラスの1つはinternalとして定義され、もう1つはprivateとして定義されています。したがって、複合タプル型の全体的なアクセスレベルはprivateです(タプルの構成要素の最小アクセスレベル)。

関数の戻り型がprivateであるため、関数宣言が有効であるためには、関数全体のアクセスレベルをprivate修飾子でマークする必要があります。

swift
private func someFunction() -> (SomeInternalClass, SomePrivateClass) {
    // 関数の実装がここに入ります
}

someFunction()の定義をpublicまたはinternal修飾子でマークすることや、デフォルトの設定であるinternalを使用することは有効ではありません。なぜなら、関数のpublicまたはinternalユーザーが、関数の戻り型で使用されるprivateクラスに適切にアクセスできない可能性があるからです。

列挙型

列挙型の個々のケースは、自動的にそれが属する列挙型と同じアクセスレベルを受け取ります。個々の列挙型ケースに対して異なるアクセスレベルを指定することはできません。

以下の例では、CompassPoint列挙型は明示的なアクセスレベルとしてpublicを持っています。したがって、列挙型ケースnorthsoutheastwestpublicアクセスレベルを持ちます。

swift
public enum CompassPoint {
    case north
    case south
    case east
    case west
}

生の値と関連値

列挙型定義の生の値や関連値に使用される型は、列挙型のアクセスレベルと同じかそれ以上のアクセスレベルを持つ必要があります。たとえば、internalアクセスレベルの列挙型の生の値の型としてprivate型を使用することはできません。

ネスト型

ネスト型のアクセスレベルは、その包含型と同じです。ただし、包含型がpublicでない限り、ネスト型は自動的にinternalアクセスレベルを持ちます。public型内のネスト型を公開したい場合は、そのネスト型を明示的にpublicとして宣言する必要があります。

サブクラス化

現在のアクセスコンテキストでアクセスできるクラスで、サブクラス化できるクラスは、サブクラスと同じモジュール内で定義されているクラスです。また、別のモジュールで定義されたopenクラスもサブクラス化できます。サブクラスは、そのスーパークラスよりも高いアクセスレベルを持つことはできません。たとえば、internalスーパークラスのpublicサブクラスを書くことはできません。

さらに、同じモジュール内で定義されたクラスの場合、特定のアクセスコンテキストで表示される任意のクラスメンバー(メソッド、プロパティ、イニシャライザ、サブスクリプト)をオーバーライドできます。別のモジュールで定義されたクラスの場合、任意のopenクラスメンバーをオーバーライドできます。

オーバーライドは、スーパークラスのバージョンよりもアクセス可能な継承クラスメンバーを作成できます。以下の例では、クラスAfile-privateメソッドsomeMethod()を持つpublicクラスです。クラスBは、アクセスレベルがinternalに減少したAのサブクラスです。それにもかかわらず、クラスBは、アクセスレベルがinternalであるsomeMethod()のオーバーライドを提供します。これは、someMethod()の元の実装よりも高いアクセスレベルです。

swift
public class A {
    fileprivate func someMethod() {}
}

internal class B: A {
    override internal func someMethod() {}
}

サブクラスメンバーが、スーパークラスメンバーよりも低いアクセス許可を持つスーパークラスメンバーを呼び出すことも有効です。スーパークラスメンバーの呼び出しが許可されたアクセスレベルコンテキスト内(つまり、file-privateメンバー呼び出しの場合はスーパークラスと同じソースファイル内、internalメンバー呼び出しの場合はスーパークラスと同じモジュール内)で行われる限りです。

swift
public class A {
    fileprivate func someMethod() {}
}

internal class B: A {
    override internal func someMethod() {
        super.someMethod()
    }
}

スーパークラスAとサブクラスBが同じソースファイル内で定義されているため、BsomeMethod()の実装がsuper.someMethod()を呼び出すことは有効です。

定数、変数、プロパティ、サブスクリプト

定数、変数、プロパティは、その型よりも公開されることはできません。たとえば、private型のpublicプロパティを書くことは有効ではありません。同様に、サブスクリプトは、そのインデックス型または戻り型よりも公開されることはできません。

定数、変数、プロパティ、サブスクリプトがprivate型を使用する場合、その定数、変数、プロパティ、サブスクリプトもprivateとしてマークする必要があります。

swift
private var privateInstance = SomePrivateClass()

ゲッターとセッター

定数、変数、プロパティ、サブスクリプトのゲッターとセッターは、自動的にそれらが属する定数、変数、プロパティ、サブスクリプトと同じアクセスレベルを受け取ります。

セッターに対応するゲッターよりも低いアクセスレベルを与えて、その変数、プロパティ、サブスクリプトの読み書き範囲を制限できます。varまたはサブスクリプトの導入子の前にfileprivate(set)private(set)internal(set)package(set)を書いて、低いアクセスレベルを割り当てます。

Note
このルールは、格納プロパティと計算プロパティの両方に適用されます。格納プロパティに対して明示的なゲッターとセッターを書かない場合でも、Swiftは格納プロパティのバックストレージにアクセスするための暗黙的なゲッターとセッターを合成します。fileprivate(set)private(set)internal(set)package(set)を使用して、計算プロパティの明示的なセッターと同じ方法で、この合成されたセッターのアクセスレベルを変更します。

以下の例では、TrackedStringという構造体を定義し、文字列プロパティが変更された回数を追跡します。

swift
struct TrackedString {
    private(set) var numberOfEdits = 0
    var value: String = "" {
        didSet {
            numberOfEdits += 1
        }
    }
}

TrackedString構造体は、valueという名前の格納文字列プロパティを定義し、初期値として""(空の文字列)を持ちます。この構造体は、numberOfEditsという名前の格納整数プロパティも定義し、valueが変更されるたびにその回数を追跡します。この変更追跡は、valueプロパティのdidSetプロパティオブザーバを使用して実装されており、valueプロパティが新しい値に設定されるたびにnumberOfEditsをインクリメントします。

TrackedString構造体とvalueプロパティは、明示的なアクセスレベル修飾子を提供していないため、デフォルトのアクセスレベルであるinternalを受け取ります。ただし、numberOfEditsプロパティのアクセスレベルはprivate(set)修飾子でマークされており、プロパティのゲッターはデフォルトのアクセスレベルであるinternalを持ちますが、プロパティはTrackedString構造体の一部であるコードからのみ設定可能です。これにより、TrackedStringnumberOfEditsプロパティを内部的に変更できますが、構造体の定義外で使用される場合は読み取り専用プロパティとして提示されます。

TrackedStringインスタンスを作成し、その文字列値を数回変更すると、numberOfEditsプロパティの値が変更回数に一致することがわかります。

swift
var stringToEdit = TrackedString()
stringToEdit.value = "This string will be tracked."
stringToEdit.value += " This edit will increment numberOfEdits."
stringToEdit.value += " So will this one."
print("The number of edits is \(stringToEdit.numberOfEdits)")
// Prints "The number of edits is 3"

別のソースファイルからnumberOfEditsプロパティの現在の値を照会することはできますが、別のソースファイルからプロパティを変更することはできません。この制限により、TrackedStringの編集追跡機能の実装の詳細が保護されますが、その機能の一部に便利にアクセスできます。

ゲッターとセッターの両方に明示的なアクセスレベルを割り当てることもできます。以下の例では、TrackedString構造体のバージョンを示しており、構造体は明示的なアクセスレベルとしてpublicを持っています。したがって、構造体のメンバー( numberOfEditsプロパティを含む)はデフォルトでinternalアクセスレベルを持ちます。numberOfEditsプロパティのゲッターをpublicにし、プロパティのセッターをprivateにするには、publicおよびprivate(set)アクセスレベル修飾子を組み合わせます。

swift
public struct TrackedString {
    public private(set) var numberOfEdits = 0
    public var value: String = "" {
        didSet {
            numberOfEdits += 1
        }
    }
    public init() {}
}

イニシャライザ

カスタムイニシャライザには、初期化する型と同じかそれ以下のアクセスレベルを割り当てることができます。唯一の例外は、必須イニシャライザ(Required Initializers)です。必須イニシャライザは、そのクラスと同じアクセスレベルを持つ必要があります。

関数およびメソッドのパラメータと同様に、イニシャライザのパラメータの型は、イニシャライザ自体のアクセスレベルよりも非公開にすることはできません。

デフォルトイニシャライザ

デフォルトイニシャライザで説明されているように、Swiftは、すべてのプロパティにデフォルト値を提供し、少なくとも1つのイニシャライザを提供しない構造体または基本クラスに対して、引数なしのデフォルトイニシャライザを自動的に提供します。

デフォルトイニシャライザは、その型が初期化する型と同じアクセスレベルを持ちます。ただし、その型がpublicとして定義されている場合を除きます。publicとして定義された型の場合、デフォルトイニシャライザはinternalと見なされます。別のモジュールで使用する場合に引数なしのイニシャライザで初期化可能なpublic型にしたい場合は、その型の定義の一部として明示的にpublic引数なしのイニシャライザを提供する必要があります。

構造体型のデフォルトメンバワイズイニシャライザ

構造体型のデフォルトメンバワイズイニシャライザは、構造体の格納プロパティのいずれかがprivateである場合、privateと見なされます。同様に、構造体の格納プロパティのいずれかがfile-privateである場合、イニシャライザはfile-privateと見なされます。それ以外の場合、イニシャライザはinternalアクセスレベルを持ちます。

上記のデフォルトイニシャライザと同様に、別のモジュールで使用する場合にメンバワイズイニシャライザで初期化可能なpublic構造体型にしたい場合は、その型の定義の一部として明示的にpublicメンバワイズイニシャライザを提供する必要があります。

プロトコル

プロトコル型に明示的なアクセスレベルを割り当てたい場合は、そのプロトコルを定義する時点で行います。これにより、特定のアクセスコンテキスト内でのみ採用できるプロトコルを作成できます。

プロトコル定義内の各要件のアクセスレベルは、自動的にプロトコルと同じアクセスレベルに設定されます。プロトコルをサポートするプロトコル要件に対して異なるアクセスレベルを設定することはできません。これにより、プロトコルを採用する任意の型でプロトコルのすべての要件が表示されることが保証されます。

Note
publicプロトコルを定義する場合、プロトコルの要件は実装時にそれらの要件に対してpublicアクセスレベルを必要とします。この動作は、public型定義がその型のメンバーに対してinternalアクセスレベルを暗示する他の型とは異なります。

プロトコルの継承

既存のプロトコルから継承する新しいプロトコルを定義する場合、新しいプロトコルは継承するプロトコルと同じアクセスレベルを持つことができます。たとえば、internalプロトコルから継承するpublicプロトコルを書くことはできません。

プロトコルの準拠

型は、型自体よりも低いアクセスレベルのプロトコルに準拠できます。たとえば、他のモジュールで使用できるpublic型を定義できますが、その準拠は内部プロトコルの定義モジュール内でのみ使用できます。

型が特定のプロトコルに準拠するコンテキストは、型のアクセスレベルとプロトコルのアクセスレベルの最小値です。たとえば、型がpublicであり、準拠するプロトコルがinternalである場合、その型のプロトコル準拠もinternalです。

型をプロトコルに準拠させるか、プロトコルに準拠するように型を拡張する場合、プロトコル準拠に対する型の実装が、そのプロトコル準拠のアクセスレベルと同じかそれ以上のアクセスレベルを持つことを確認する必要があります。たとえば、public型がinternalプロトコルに準拠する場合、その型の各プロトコル要件の実装は少なくともinternalである必要があります。

Note
Swiftでは、Objective-Cと同様に、プロトコル準拠はグローバルです。プログラム内で同じ型が2つの異なる方法でプロトコルに準拠することはできません。

拡張

クラス、構造体、列挙型を、そのクラス、構造体、列挙型が利用可能な任意のアクセスコンテキストで拡張できます。拡張に追加された型メンバーは、拡張される元の型で宣言された型メンバーと同じデフォルトのアクセスレベルを持ちます。publicまたはinternal型を拡張する場合、追加された新しい型メンバーはデフォルトでinternalアクセスレベルを持ちます。file-private型を拡張する場合、追加された新しい型メンバーはデフォルトでfile-privateアクセスレベルを持ちます。private型を拡張する場合、追加された新しい型メンバーはデフォルトでprivateアクセスレベルを持ちます。

代わりに、拡張に明示的なアクセスレベル修飾子(たとえば、private)をマークして、拡張内で定義されたすべてのメンバーに対して新しいデフォルトのアクセスレベルを設定できます。この新しいデフォルトは、拡張内の個々の型メンバーに対して引き続きオーバーライドできます。

プロトコル準拠を追加するために拡張を使用している場合、明示的なアクセスレベル修飾子を提供することはできません。代わりに、プロトコル自体のアクセスレベルが、拡張内の各プロトコル要件実装のデフォルトのアクセスレベルを提供します。

拡張内のプライベートメンバー

クラス、構造体、列挙型を拡張する拡張が、元の型の宣言と同じファイルにある場合、拡張内のコードは元の型の宣言の一部として書かれたかのように振る舞います。その結果、次のことができます。

  • 元の宣言でプライベートメンバーを宣言し、同じファイル内の拡張からそのメンバーにアクセスします。
  • 1つの拡張でプライベートメンバーを宣言し、同じファイル内の別の拡張からそのメンバーにアクセスします。
  • 拡張でプライベートメンバーを宣言し、同じファイル内の元の宣言からそのメンバーにアクセスします。

この動作により、型にプライベートエンティティがあるかどうかに関係なく、コードを整理するために拡張を同じ方法で使用できます。たとえば、次のシンプルなプロトコルを考えます。

swift
protocol SomeProtocol {
    func doSomething()
}

次のように、拡張を使用してプロトコル準拠を追加できます。

swift
struct SomeStruct {
    private var privateVariable = 12
}

extension SomeStruct: SomeProtocol {
    func doSomething() {
        print(privateVariable)
    }
}

ジェネリクス

ジェネリック型またはジェネリック関数のアクセスレベルは、ジェネリック型または関数自体のアクセスレベルと、型パラメータの型制約のアクセスレベルの最小値です。

型エイリアス

定義する型エイリアスは、アクセス制御の目的で別個の型として扱われます。型エイリアスは、それがエイリアスする型のアクセスレベルと同じかそれ以下のアクセスレベルを持つことができます。たとえば、private型エイリアスは、privatefile-privateinternalpublic、またはopen型をエイリアスできますが、public型エイリアスは、internalfile-private、またはprivate型をエイリアスすることはできません。

Note
このルールは、プロトコル準拠を満たすために使用される関連型の型エイリアスにも適用されます。