Swift readonly external、readwrite internalプロパティ


103

Swiftでは、プロパティが外部的に読み取り専用であるが、それを所有するクラス(およびサブクラス)によって内部的に変更可能な共通パターンを定義する従来の方法は何ですか。

Objective-Cには、次のオプションがあります。

  • インターフェイスでプロパティを読み取り専用として宣言し、クラス拡張を使用してプロパティに内部的にアクセスします。これはメッセージベースのアクセスであるため、KVO、原子性などとうまく連携します。
  • インターフェイスでプロパティを読み取り専用として宣言しますが、内部でバッキングivarにアクセスします。ivarのデフォルトアクセスは保護されているため、これはクラス階層で適切に機能します。サブクラスも値を変更できますが、それ以外の場合、フィールドは読み取り専用です。

Javaでは、規約は次のとおりです。

  • プロテクトフィールドを宣言し、パブリックな読み取り専用のゲッター(メソッド)を実装します。

Swiftのイディオムは何ですか?

回答:


219

クラスプロパティを指定すると、プロパティ宣言の前に括弧を付けて、getまたはset括弧の後にアクセス修飾子を付けて、別のアクセスレベルを指定できます。たとえば、パブリックゲッターとプライベートセッターを持つクラスプロパティは、次のように宣言されます。

private(set) public var readonlyProperty: Int

推奨読書:ゲッターとセッター

マーティンのアクセシビリティレベルに関する考慮事項は引き続き有効です。つまり、protected修飾子はなくinternal、モジュールへのアクセスのみを制限privateし、現在のファイルのみにpublic制限します。

Swift 3ノート

2つの新しいアクセス修飾子、fileprivateおよびopen一方で、言語に追加されているprivatepublic、わずかに変更されました。

  • openクラスおよびクラスメンバーにのみ適用されます。クラスをサブクラス化したり、メンバーが定義されているモジュールの外部でメンバーをオーバーライドできるようにするために使用されます。public代わりに、クラスまたはメンバーをパブリックにアクセス可能にしますが、継承またはオーバーライドはできません

  • privateメンバーを表示し、囲んでいる宣言からのみアクセスできるようにしfileprivateますが、それが含まれているファイル全体に対しては

詳細はこちら


いいね!(不足しているvarキーワードを追加して自由にコンパイルできます。)
Martin R

どうもありがとう:)私は通常、遊び場からコピーして貼り付けますが、今回はおそらく間違っています。
Antonio

10
2015年1月の時点で、外部クラスが正しくない場合、この構文は完全に正しくないpublicことに注意してください。internalつまり、まったくまたはまったく何もないはずです(デフォルトは、クラスが何であれ- publicまたはinternal)-すなわちprivate(set) var readonlyProperty: Int
Grimxn

1
構文は、コードの直前に私がパブリックゲッターとプライベートセッターを使用してクラスプロパティを記述したことを考慮すれば、正しい構文です。これは単なる例です。しかし、はい。プロパティのアクセス修飾子は、クラス/構造体のアクセス修飾子と「互換性」がある必要があります。
Antonio

最後の段落については、回答が書かれてから変更されていると思いますがprivate、現在はファイルではなく現在の宣言fileprivateに制限されており、現在のファイルに制限することができます。またpublic、いくつかの制限があり、制限openなしに必要です。詳細はこちら
Nigel B. Peck 2016

2

@Antonioに従って、単一のプロパティを使用して、readOnlyプロパティ値としてパブリックおよびreadWriteプライベートにアクセスできます。以下は私のイラストです:

class MyClass {

    private(set) public var publicReadOnly: Int = 10

    //as below, we can modify the value within same class which is private access
    func increment() {
        publicReadOnly += 1
    }

    func decrement() {
        publicReadOnly -= 1
    }
}

let object = MyClass()
print("Initial  valule: \(object.publicReadOnly)")

//For below line we get the compile error saying : "Left side of mutating operator isn't mutable: 'publicReadOnly' setter is inaccessible"
//object.publicReadOnly += 1

object.increment()
print("After increment method call: \(object.publicReadOnly)")

object.decrement()
print("After decrement method call: \(object.publicReadOnly)")

そしてここに出力があります:

  Initial  valule: 10
  After increment method call: 11
  After decrement method call: 10
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.