2016-08-31 5 views
8

私はGetプロパティとSetプロパティを使用する理由についていくつかの調査を行っていました。Swiftのゲッターとセッター - 代わりにWillSetとDidSetを使用するのは理にかなっていますか?

あなたはあなただけから入手することができますプロパティを持つようにしたい場合は、あなたが実際に 財産

  • を設定する前に/何かをチェックしたいと思うとき、私はそれ

    1. のための3つの主な理由を気づきましたそれは (多分私は推測するセキュリティの目的のため?)、または別のアクセス レベルを与える。
    2. 代替表現を使用して プロパティを公開しながら、プロパティの内部表現を非表示にします。

    を(私はとにかく 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を使用して、以下のこの他の例そして、オブザーバーを設定しました

    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 
        } 
    } 
    

    私はそれぞれの実装の利点と欠点を知りたいと思っています。事前に

    おかげ

  • +0

    非常に興味深い質問ですが、暴徒が発見されて以来、本当に助けになることはできません。 .. –

    +0

    willSetとdidSetは** observors **です。彼らはゲッター/セッターとはまったく異なります。 (Swiftのプロパティ(プロトコル拡張など)はプロパティでなくてもよく、それらは計算プロパティです)。 、それは非常に頻繁に**あなたが退屈なプロパティ/ゲッター/セッターパターンを使用することについて**気にする必要はありません。 – Fattie

    答えて

    3

    あなたの質問は、実行時エラー対時間をコンパイルするために沸きます。あなたの3つの質問に対処するために:

    1. はい、willCheckはあなたの唯一のオプションは
    2. 読み取り専用のプロパティは2種類に分類され、ここで:(a)は、これらの値が他のプロパティから派生する、例えば、それらの和; (b)ユーザーが変更することはできませんが、変更することはできません。最初のタイプは本当にセッターを持っていません。 2番目の型はpublic getterとプライベートセッターを持っています。コンパイラはそれをチェックするのに役立ち、プログラムはコンパイルされません。 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 
    

    ノートはおよそprivateスウィフト3対スウィフト2:あなたはスウィフト2遊び場でこれをしようとした場合、あなたがt.greeting = "Goodbye world"作品を見つけますちょうど良い。これは、Swift 2に奇妙なアクセスレベル指定子があるためです。privateは「現在のファイル内でのみアクセス可能」を意味します。クラス定義とサンプルコードを別々のファイルに分けてください.Xcodeはそれに不満を持ちます。 Swift 3では、fileprivateに変更され、privateというキーワードがJavaおよび.NETと類似しています。

    関連する問題