8

プロパティに Get と Set を使用する必要がある理由について調査していました。

その主な理由は3つあることに気づきました

  1. 実際にプロパティを設定する前に何かをしたい/確認したい場合
  2. そこからのみ取得できるプロパティが必要な場合(おそらくセキュリティ上の理由からだと思いますか?)、または異なるアクセスレベルを付与したい場合。
  3. 代替表現を使用してプロパティを公開しながら、プロパティの内部表現を非表示にします。(とにかく Set 関数を使用して間違った場所にアクセスできるので、私にとってはあまり意味がありません)

以下のコードは、Swift でプロパティの Get および Set を実装する方法の例であり、前述の 3 つのポイントを利用しています。

class Test
{
    private var _testSet:String!
    private var _testGetOnly:String
    var testSet:String{
        get{
            return _testSet
        }
        set{
            _testSet = newValue + "you forgot this string"
        }
    }
    var testGetOnly:String!{
        get{
            return _testGetOnly
        }
    }

    init(testSet:String, testGetOnly:String)
    {
        _testSet = testSet
        _testGetOnly = testGetOnly
    }
}

しかし、以下のこの他の例も、前述のポイントを利用していますが、別の計算されたプロパティを使用してプライベート プロパティ値を返す代わりに、willSet および didSet オブザーバーを使用するだけです。

class Test
{
    var testGet:String {
        willSet{
            fatalError("Operation not allowed")
        }
    }
    var testWillSet:String!{
        didSet{
            self.testWillSet = self.testWillSet + "you forgot this string"
        }
    }
    init(testGet:String, testWillSet:String)
    {
        self.testGet = testGet
        self.testWillSet = testWillSet 
    }
}

したがって、各実装の利点と欠点を知りたいと思っています。

前もって感謝します

4

1 に答える 1

4

あなたの質問は、コンパイル時間と実行時のエラーに要約されます。3 つの質問に対処するには:

  1. はい、これwillCheckが唯一の選択肢です
  2. 読み取り専用プロパティは、次の 2 つのタイプに分類されます。(a) 値が他のプロパティから派生するもの。(b) ユーザーではなく自分で変更できるようにしたいもの。最初のタイプには本当にセッターがありません。2 番目のタイプには、パブリック ゲッターとプライベート セッターがあります。コンパイラはそれをチェックするのに役立ちますが、プログラムはコンパイルされません。をスローするとfatalErrordidSet実行時エラーが発生し、アプリケーションがクラッシュします。
  3. ユーザーに自由にいじらせたくない状態オブジェクトが存在する可能性があります。そうです、それらをユーザーから完全に隠すことができます。

あなたのコードの最初の例は、バッキング変数を定義するのに冗長すぎました - あなたはそれをする必要はありません. これらの点を説明するには:

class Test
{
    // 1. Validate the new value
    var mustBeginWithA: String = "A word" {
        willSet {
            if !newValue.hasPrefix("A") {
                fatalError("This property must begin with the letter A")
            }
        }
    }

    // 2. A readonly property
    var x: Int = 1
    var y: Int = 2
    var total: Int {
        get { return x + y }
    }

    private(set) var greeting: String = "Hello world"
    func changeGreeting() {
        self.greeting = "Goodbye world" // Even for private property, you may still
                                        // want to set it, just not allowing the user
                                        // to do so
    }

    // 3. Hide implementation detail
    private var person = ["firstName": "", "lastName": ""]
    var firstName: String {
        get { return person["firstName"]! }
        set { person["firstName"] = newValue }
    }

    var lastName: String {
        get { return person["lastName"]! }
        set { person["lastName"] = newValue }
    }

    var fullName: String {
        get { return self.firstName + " " + self.lastName }
        set {
            let components = newValue.componentsSeparatedByString(" ")
            self.firstName = components[0]
            self.lastName = components[1]
        }
    }
}

使用法:

let t = Test()
t.mustBeginWithA = "Bee"        // runtime error

t.total = 30                    // Won't compile

t.greeting = "Goodbye world"    // Won't compile. The compiler does the check for you
                                // instead of a crash at run time

t.changeGreeting()              // OK, greeting now changed to "Goodbye world"

t.firstName = "John"            // Users have no idea that they are actually changing 
t.lastName = "Smith"            // a key in the dictionary and there's no way for them
                                // to access that dictionary

t.fullName = "Bart Simpsons"    // You do not want the user to change the full name
                                // without making a corresponding change in the
                                // firstName and lastName. With a custome setter, you
                                // can update both firstName and lastName to maintain
                                // consistency

privateSwift 2 と Swift 3 での注意点: Swift 2 プレイグラウンドでこれを試してみると、t.greeting = "Goodbye world"問題なく動作することがわかります。これは、Swift 2 にprivate「現在のファイル内でのみアクセス可能」という奇妙なアクセス レベル指定子があるためです。クラス定義とサンプルコードを別々のファイルに分けると、Xcode が文句を言います。Swift 3 では、Java や .NET に似たキーワードをfileprivateより明確にし、キーワードを保存するように変更されました。private

于 2016-09-01T04:29:06.267 に答える