Swiftにおける属性の宣言と役割の詳細

4989 ワード

一、引用
プロパティは、値をクラス、構造体、列挙に関連付けます.Swiftの属性はストレージ属性と計算属性の2種類に分けられ、ストレージ属性は1つの値を格納するために使用され、クラスと構造体にのみ使用され、計算属性は1つの値を計算するために使用され、クラス、構造体、列挙に使用することができる.
二、記憶属性
ストレージ属性は変数または定数を使用して値を格納します.ストレージ属性を宣言するときにデフォルト値を設定するか、構築例で値の設定を行うことができます.属性はポイント構文でアクセスできます.構造体のストレージ属性のサンプルコードは次のとおりです.

struct MyStruct {
  var property1 = 1
  var property2:Int
}
var obj = MyStruct(property1: 1, property2: 2)
// 
print(obj.property1,obj.property2)

このような構造体では、let定数として宣言された属性がある場合、この属性は変更できません.また、構造体のインスタンスを作成するときにletを使用して作成する場合は、構造体のプロパティが変数であっても変更できません.これはクラスと大きく違います.
もう1つのストレージ属性は遅延ストレージ属性と呼ばれ、クラスのいくつかの属性はクラスインスタンスのたびに使用されるわけではなく、いくつかの属性の構造に多くの時間がかかる可能性がある場合を想定することができる.この場合、比較的賢い設計はクラスがインスタンス化されている場合、このような属性は構築されず、次のクラスのインスタンスがこの属性を使用すると、この属性が構築される.このような属性は遅延記憶属性と呼ばれ、lazyキーワードを使用して宣言されます.例は以下のとおりです.

// 
class MyClass1 {
  init(){
    print("MyClass1 ")
  }
}
class MyClass2 {
  // 
  lazy var body = MyClass1()
}
// MyClass2   body   
var obj2 = MyClass2()
//     body body 
obj2.body

なお、遅延構造属性を複数のスレッドで使用する場合、一度だけ構築されるとは保証されない.
三、計算属性
簡単な理解では、計算属性は独立して値を格納するための属性ではなく、開発者は、主に計算によって他の記憶属性の値を取得または設定するための計算方法として理解することができる.例は次のとおりです.

struct Circle {
  // 
  var center:(Double,Double)
  // 
  var r:Double
  //   
  var l:Double{
    get{
      // 
      return 2.0*r*M_PI
    }
    set{
      //   newValue
      r = newValue/(M_PI*2)
    }
  }
}
var circle = Circle(center: (0,0), r: 2)
print(circle.l)
circle.l=24
print(circle.r)

上記のプレゼンテーションコードから分かるように、l属性は新しい属性ではなく、r属性によってlを計算するか、lによってrを逆押し出しするか、計算属性には2つのコードブロックsetとgetを作成することができ、setコードブロックはオプションであり、newValueパラメータがデフォルトで生成されて外部から伝達されたデータが伝達され、getコードブロックは実現しなければならない.もちろんgetコードブロックのみを実装することもできますが、この場合、この属性は読み取り専用の計算属性になり、取得のみ可能で、設定できません.また、開発者はsetコードブロックの後に外部から送信されたパラメータを受信するためにパラメータ名をカスタマイズすることもできます.例は以下の通りです.

struct Circle {
  // 
  var center:(Double,Double)
  // 
  var r:Double
  //   
  var l:Double{
    get{
      // 
      return 2.0*r*M_PI
    }
    set(newL){
      //   newValue
      r = newL/(M_PI*2)
    }
  }
}

読み取り専用の計算プロパティは、setコードブロックがないため、キーワードgetとカッコを省略しても、曖昧さは生じません.例は次のとおりです.

struct Point {
  var x:Double
  var y:Double
  var center:(Double,Double){
    return (x/2,y/2)
  }
}


四、属性リスナー
Swiftの計算属性のgetとsetメソッドとObjective-Cのgetとsetメソッドは実際には同じではありません.Objective-Cはsetとgetメソッドを提供し、開発者に属性が取得または設定されるときにカスタマイズされた操作を行うことができます.この部分の開発はSwiftで属性リスナーによって実現されることを求めます.
属性リスナーにはwillSetとdidSetの2種類があり、willSetは属性値が変化するときに実行され、didSetは属性値が変化したときに実行され、変化前後の値が入力されます.例は次のとおりです.

struct Point {
  var x:Double
  var y:Double{
    willSet{
      print(" , :",newValue)
    }
    didSet{
      print(" , :",oldValue)
    }
  }
  var center:(Double,Double){
    return (x/2,y/2)
  }
}
var point = Point(x: 3, y: 3)
// 
/*
  , : 4.0
  , : 3.0
 */
point.y=4

willSetではデフォルトでnewValueという名前のパラメータが生成され、didSetではデフォルトでoldValueという名前のパラメータが生成されます.これらのパラメータの名前をカスタマイズすることもできます.例は次のとおりです.

struct Point {
  var x:Double
  var y:Double{
    willSet(new){
      print(" , :",new)
    }
    didSet(old){
      print(" , :",old)
    }
  }
  var center:(Double,Double){
    return (x/2,y/2)
  }
}


五、インスタンス属性とタイプ属性
インスタンスプロパティは、1つのタイプのインスタンスに対して、タイププロパティは直接タイプに対してです.各ペアのタイプはインスタンス化され、そのインスタンスには独立したインスタンス属性がありますが、タイプ属性はクラスのすべてのインスタンスで共通しています.Objective-Cでは、通常、グローバルな属性を使用してこのような効果を実現します.Swiftではstaticキーワードを使用してタイプ属性を宣言します.例は次のとおりです.

struct Point {
  // 
  static var name:String = "Point"
  // 
  static var subName:String{
    return "sub"+name
  }
  var x:Double
  var y:Double{
    willSet(new){
      print(" , :",new)
    }
    didSet(old){
      print(" , :",old)
    }
  }
  var center:(Double,Double){
    return (x/2,y/2)
  }
}
//   
print(Point.name,Point.subName)

クラスのタイプに対して属性を計算する場合、サブクラスの継承書き換えが必要な場合はstaticキーをclassキーに変更する必要があります.例は次のとおりです.

class SomeClass {
  static var storedTypeProperty = "Some value."
  static var computedTypeProperty: Int {
    return 27
  }
  // 
  class var overrideableComputedTypeProperty: Int {
    return 107
  }
}