Swift:ベース(20)属性

6649 ワード

Swift属性


Swiftプロパティは、値を特定のクラス、構造、または列挙に関連付けます.
属性は、ストレージ属性と計算属性に分けられます.
ストレージのプロパティ
計算プロパティ
インスタンスの一部として定数または変数を格納
値の計算(格納ではなく)
クラスおよび構造体用
クラス、構造体、列挙に使用
ストレージ属性と計算属性は、通常、特定のタイプのインスタンスに使用されます.
属性は、タイプ自体にも直接使用できます.この属性をタイプ属性と呼びます.
また、アトリビュートオブザーバを定義してアトリビュート値の変化を監視し、カスタム操作をトリガーすることもできます.アトリビュートオブザーバは、自分が書いたストレージアトリビュートに追加したり、親から継承したアトリビュートに追加したりできます.

ストレージのプロパティ


簡単に言えば、1つのストレージ属性は、特定のクラスまたは構造体のインスタンスに格納される定数または変数です.
ストレージ属性は、変数ストレージ属性(キーワードvarで定義)でも定数ストレージ属性(キーワードletで定義)でもよい.
  • は、記憶属性を定義するときにデフォルト値
  • を指定することができる.
  • は、構築中に記憶属性の値を設定または変更することもできるし、定数記憶属性の値
  • を変更することもできる.
    import Cocoa
    
    struct Number
    {
       var digits: Int
       let pi = 3.1415
    }
    
    var n = Number(digits: 12345)
    n.digits = 67
    
    print("\(n.digits)")
    print("\(n.pi)")
    

    以上のプログラムの実行出力結果は以下の通りです.
    67
    3.1415
    

    次のコードを考慮します.
    let pi = 3.1415
    

    コードではpiはストレージ属性を定義するときにデフォルト値(pi=3.1415)を指定するので、構造体をいつインスタンス化しても変更されません.
    定数ストレージ属性を定義している場合は、次のように変更しようとするとエラーが表示されます.
    import Cocoa
    
    struct Number
    {
        var digits: Int
        let numbers = 3.1415
    }
    
    var n = Number(digits: 12345)
    n.digits = 67
    
    print("\(n.digits)")
    print("\(n.numbers)")
    n.numbers = 8.7
    

    以上のプログラムは、実行するとエラーが表示されます.エラーは以下の通りです.
    error: cannot assign to property: 'numbers' is a 'let' constant
    n.numbers = 8.7
    
    'numbers'は定数で、修正できません.

    遅延ストレージ属性


    遅延ストレージ属性とは、最初に呼び出されたときにその初期値が計算される属性です.
    プロパティ宣言の前にlazyを使用して、遅延ストレージプロパティを表示します.
    注意:インスタンス構築が完了するまで属性の値が得られない可能性があるため、遅延ストレージ属性を変数として宣言する必要があります(varキーワードを使用).定数属性は、構築プロセスが完了する前に初期値が必要であるため、遅延属性として宣言できません.
    遅延ストレージのプロパティは、一般的に次のように使用されます.
  • は、オブジェクトの作成を遅延します.
  • 属性の値が他の未知クラス
  • に依存する場合
    import Cocoa
    
    class sample {
        lazy var no = number() // `var`  
    }
    
    class number {
        var name = " "
    }
    
    var firstsample = sample()
    print(firstsample.no.name)
    

    以上のプログラムの実行出力結果は以下の通りです.
     
    

    インスタンス変数


    Objective-Cの経験がある場合は、Objective-Cがクラスインスタンスに値と参照を格納する2つの方法を提供することを知っておく必要があります.プロパティの場合、インスタンス変数をプロパティ値のバックエンドとして格納することもできます.
    Swiftプログラミング言語ではこれらの理論を属性で統一して実現する.Swiftの属性には対応するインスタンス変数がなく,属性のバックエンドストレージにも直接アクセスできない.これにより、異なるシーンでのアクセス方法の問題を回避し、プロパティの定義を文に簡略化できます.
    名前、タイプ、メモリ管理フィーチャーを含む1つのタイプのプロパティのすべての情報は、ユニークな場所(タイプ定義)で定義されます.

    計算プロパティ


    ストレージ属性に加えて、クラス、構造体、列挙は計算属性を定義し、計算属性は直接値を格納するのではなく、getterを提供して値を取得し、オプションのsetterを提供して他の属性または変数の値を間接的に設定します.
    import Cocoa
    
    class sample {
        var no1 = 0.0, no2 = 0.0
        var length = 300.0, breadth = 150.0
        
        var middle: (Double, Double) {
            get{
                return (length / 2, breadth / 2)
            }
            set(axis){
                no1 = axis.0 - (length / 2)
                no2 = axis.1 - (breadth / 2)
            }
        }
    }
    
    var result = sample()
    print(result.middle)
    result.middle = (0.0, 10.0)
    
    print(result.no1)
    print(result.no2)
    

    以上のプログラムの実行出力結果は以下の通りです.
    (150.0, 75.0)
    -150.0
    -65.0
    

    計算属性のsetterに新しい値を表すパラメータ名が定義されていない場合は、デフォルト名newValueを使用します.

    読み取り専用計算プロパティ


    getterにsetterがない計算属性だけが読み取り専用計算属性です.
    読み取り専用の計算プロパティは、常に値を返します.ポイント(.)演算子はアクセスしますが、新しい値は設定できません.
    import Cocoa
    
    class film {
        var head = ""
        var duration = 0.0
        var metaInfo: [String:String] {
            return [
                "head": self.head,
                "duration":"\(self.duration)"
            ]
        }
    }
    
    var movie = film()
    movie.head = "Swift  "
    movie.duration = 3.09
    
    print(movie.metaInfo["head"]!)
    print(movie.metaInfo["duration"]!)
    

    以上のプログラムの実行出力結果は以下の通りです.
    Swift  
    3.09
    

    注意:varキーを使用して、値が固定されていないため、読み取り専用の計算プロパティを含む計算プロパティを定義する必要があります.letキーワードは定数属性を宣言するためにのみ使用され、初期化後に変更できない値を表します.

    属性オブザーバ


    プロパティ・オブザーバは、プロパティ値の変化を監視し、応答します.プロパティが値を設定されるたびにプロパティ・オブザーバが呼び出され、新しい値が現在の値と同じ場合でも例外ではありません.
    遅延ストレージアトリビュート以外のストレージアトリビュートにアトリビュートオブザーバを追加するか、アトリビュートを再ロードすることで継承されたアトリビュート(ストレージアトリビュートと計算アトリビュートを含む)にアトリビュートオブザーバを追加することができます.
    注意:setterによって値の変化を直接監視および応答できるため、リロードできない計算プロパティにプロパティ・オブザーバを追加する必要はありません.
    アトリビュートに次の1つまたはすべてのオブジェクトを追加できます.
  • willSetは、新しい値を設定する前に
  • を呼び出す.
  • didSetは、新しい値が設定された直後に
  • を呼び出す.
  • willSetおよびdidSetオブザーバは、属性初期化中に
  • を呼び出すことはありません.
    import Cocoa
    
    class Samplepgm {
        var counter: Int = 0{
            willSet(newTotal){
                print(" : \(newTotal)")
            }
            didSet{
                if counter > oldValue {
                    print("  \(counter - oldValue)")
                }
            }
        }
    }
    let NewCounter = Samplepgm()
    NewCounter.counter = 100
    NewCounter.counter = 800
    

    以上のプログラムの実行出力結果は以下の通りです.
     : 100
      100
     : 800
      700
    

    グローバル変数とローカル変数


    計算プロパティおよびプロパティオブザーバによって記述されるモードは、グローバル変数およびローカル変数にも使用できます.
    ローカル変数
    グローバル変数
    関数、メソッド、または閉パッケージの内部で定義された変数.
    関数、メソッド、閉パッケージ、または任意のタイプ以外で定義された変数.
    値の保存と取得に使用します.
    値の保存と取得に使用します.
    ストレージ属性は、値を取得および設定するために使用されます.
    ストレージ属性は、値を取得および設定するために使用されます.
    属性の計算にも使用します.
    属性の計算にも使用します.

    タイプのプロパティ


    タイププロパティは、タイプ定義の一部としてタイプの最外層のカッコ({})に書かれています.
    キーワードstaticを使用して値タイプのタイプ属性を定義し、キーワードclassを使用してクラスのタイプ属性を定義します.
    struct Structname {
       static var storedTypeProperty = " "
       static var computedTypeProperty: Int {
          //   Int  
       }
    }
    
    enum Enumname {
       static var storedTypeProperty = " "
       static var computedTypeProperty: Int {
          //   Int  
       }
    }
    
    class Classname {
       class var computedTypeProperty: Int {
          //   Int  
       }
    }
    

    注:例の計算タイプ属性は読み取り専用ですが、インスタンス計算属性の構文と同様に、読み取り可能で書き込み可能な計算タイプ属性を定義することもできます.

    タイプ属性の値の取得と設定


    インスタンスのプロパティと同様に、タイププロパティへのアクセスもポイント演算子(.)で行ないます.ただし、タイププロパティは、インスタンスではなくタイプ自体で取得および設定されます.例は次のとおりです.
    import Cocoa
    
    struct StudMarks {
       static let markCount = 97
       static var totalCount = 0
       var InternalMarks: Int = 0 {
          didSet {
             if InternalMarks > StudMarks.markCount {
                InternalMarks = StudMarks.markCount
             }
             if InternalMarks > StudMarks.totalCount {
                StudMarks.totalCount = InternalMarks
             }
          }
       }
    }
    
    var stud1Mark1 = StudMarks()
    var stud1Mark2 = StudMarks()
    
    stud1Mark1.InternalMarks = 98
    print(stud1Mark1.InternalMarks) 
    
    stud1Mark2.InternalMarks = 87
    print(stud1Mark2.InternalMarks)
    

    以上のプログラムの実行出力結果は以下の通りです.
    97
    87