swiftのプロパティ


プロパティは、値を特定のクラス、構造、または列挙に関連付けます.ストレージ属性は、インスタンスの一部分として定数または変数を格納し、ストレージではなく属性計算の一値を計算します.計算属性はクラス、構造体、列挙に適用でき、記憶属性はクラスと構造体にのみ適用できます.
ストレージ属性と計算属性は、通常、特定のタイプのインスタンスに関連付けられます.ただし,属性はタイプブックに直接適用することもでき,この属性をタイプ属性と呼ぶ.
さらに、属性オブジェクトを定義して属性値の変化を監視し、1つのプロパティ・オブザーバは、⾃⼰定義のストレージ・プロパティに追加するか、⽗クラスから継承されたプロパティに追加できます.
一、記憶属性
クラスまたは構造体のメンバー変数または定数を格納するプロパティ
struct Phone {
    var price : Float
    let brand : String
    // , 
}
var phone1 = Phone(price: 999, brand: "xiaomi1")
let phone2 = Phone(price: 1799, brand: "xiaomiNote")
//phone1 
//phone2 
phone1.price = 888
//brand  , ,brand 
// phone2 , , , 

構造体をクラスに置き換えると、
class Phone1 {
    var price : Float
    let brand : String
    init () {
        price = 10.0
        brand = "xiaomi"
    }
}

var phone3 = Phone1()
let phone4 = Phone1()
print("\(phone3.price), \(phone3.brand)")
//10.0, xiaomi
phone4.price = 100
//phone4.brand = "red mi"   // 
// phone4 , ?   
// , ,phone4 ,  phone4 = phone3   , let 

遅延ストレージのプロパティ:
遅延記憶属性とは、1回目に適用されたときにその初期値が計算される属性である.属性宣言の前にlazyを用いて遅延記憶属性を1つ表記する.
注意:属性の初期値は、インスタンス構築が完了した後に得られる可能性があるため、遅延ストレージ属性を変数(varキーワードを適用する)として宣言する必要があります.定数属性は、構築プロセスが完了する前に初期値が必要であるため、定数は遅延属性として宣言されません.
func complexCompute() -> Int {
    // 10 
    return 10
}
class MathCompute {
    lazy var computeResult = complexCompute()
    var x = 10
}
// MathCompute computeResult , , computeResult , 

二、計算属性
計算プロパティは直接値を格納しません.getterとオプションsetterを1つ提供し、他のプロパティまたは変数の値を間接的に取得および設定します.
struct Point {
    var x = 0.0, y = 0.0
}
struct Size {
    var width = 0.0, height = 0.0
}
struct Rect {
    var origin = Point()
    var size = Size()
    var center: Point {
        get {
            let centerX = origin.x + (size.width / 2)
            let centerY = origin.y + (size.height / 2)
            return Point(x: centerX, y: centerY)
        }
        set(newCenter) {
            origin.x = newCenter.x - (size.width / 2)
            origin.y = newCenter.y - (size.height / 2)
        }
    }
}
var square = Rect(origin: Point(x: 0.0, y: 0.0), size: Size(width: 10.0, height: 10.0))
let initialSquareCenter = square.center  // get
square.center = Point(x: 15.0, y: 15.0)  // set
print("square.origin is now at (\(square.origin.x), \(square.origin.y))")
//"square.origin is now at (10.0, 10.0)”

便利なsetterは、計算プロパティのsetterがテーブル⽰の新しい値のパラメータ名を定義していない場合、デフォルト名newValueを適用できることを宣言します.以下は、便利なsetter宣言を適用したRect構造体コードである.
struct AlternativeRect {
    var origin = Point()
    var size = Size()
    var center: Point {
        get {
            let centerX = origin.x + (size.width / 2)
            let centerY = origin.y + (size.height / 2)
            return Point(x: centerX, y: centerY)
        }
        set {
            origin.x = newValue.x - (size.width / 2)
            origin.y = newValue.y - (size.height / 2)
        }
    }
}

また、getterのみsetterがない読み取り専用計算プロパティもあります.読み取り専用計算プロパティはgetと{}を削除することもできます.
三、属性オブザーバ
プロパティ・オブザーバは、プロパティ値の変化を監視し、応答します.プロパティが値を設定されるたびにプロパティ・オブザーバが適用されます.新しい値が現在の値と同じ場合でも例外ではありません.
遅延ストレージ属性以外のストレージ属性に属性オブジェクトを追加することもできます.また、属性オブジェクトを再ロードすることで、継承された属性(ストレージ属性と計算属性を含む)に属性オブジェクトを追加することもできます.
注意:setterによって応答値の変化を直接監視および監視できるため、再ロードされた計算属性に属性オブジェクトを追加する必要はありません.
プロパティには、willSetが新しい値が設定される前にdidSetを適用し、新しい値が設定された後に確立する、すなわち適用する1つまたはすべてのオブザーバを追加できます.
willSetオブジェクトは、新しい属性値を定数パラメータとして送信します.willSetの実装コードでは、このパラメータに1つの名前を指定できます.指定しない場合、パラメータは使用できます.この場合、デフォルト名newValueテーブル同様に、didSetオブザーバは、古い属性値をパラメータとして伝達し、このパラメータに名前を付けたり、デフォルトのパラメータ名oldValueを適用したりすることができる.
注意:クラスのプロパティがクラスのコンストラクタに割り当てられている場合、クラスのwillSetおよびdidSetオブザーバが適用されます.
class Dog {
    var dogName : String = "littledog" {
        willSet(newDogName) { // 
            print("old dog name is \(dogName) ,and the new dog name is \(newDogName)")
        }
        didSet {  // 
            print("new dog name is \(dogName)")
        }
    }
}
var dog1 = Dog()
dog1.dogName = "bigDog"
//old dog name is littledog ,and the new dog name is bigDog
//new dog name is bigDog

class LittleDog: Dog {
    
    override init() {
        super.init()
        self.dogName = "---this is little dog---"
    }
}
var littleDog1 = LittleDog()   // ,  willSet   didSet  。
//old dog name is littledog ,and the new dog name is ---this is little dog---
//new dog name is ---this is little dog---

注意:1つのプロパティのdidSetオブジェクトに値を割り当てると、オブジェクトの前に設定した値が置き換えられます.
四、グローバル変数とローカル変数
計算プロパティおよびプロパティオブザーバによって記述されるモードは、グローバル変数およびローカル変数にも適用できます.
グローバル変数は、関数、スキーマ、閉パッケージ、または任意のタイプ以外で定義された変数です.ローカル変数は、関数、スキーマ、または閉パッケージの内部で定義された変数です.
さらに、計算型変数をグローバルまたはローカルの範囲で定義し、格納型変数のオブザーバを定義できます.計算型変数は計算属性と同一であり,1つの計算を返す値は格納値ではなく,宣言フォーマットも完全に同一である.
注意:グローバルの定数または変数はいずれも遅延計算であり、遅延記憶属性と同様であり、異なる態様は、グローバルの定数または変数がlazy特性をマークする必要がないことである.ローカル範囲の定数または変数は計算を遅延させません.
五、タイプ属性
インスタンスのプロパティは1つの特定のタイプのインスタンスに属し、タイプがインスタンス化されるたびに、インスタンス間のプロパティが互いに独立している.
また、タイプブックに属性を定義することもできます.これらの属性は、タイプがいくつあるかのインスタンスにかかわらず、1つだけです.この属性がタイプ属性です.
値タイプのストレージタイプ属性は変数または定数であり、計算タイプ属性はインスタンスの計算属性と同じで変数属性として定義できます.
注意:
インスタンスのストレージ属性とは異なり、タイプ固有のメソッドが初期化中にアプリケーションコンストラクタにタイプ属性に値を割り当てるため、ストレージタイプ属性にデフォルト値を指定する必要があります.
タイプ属性構文:
struct SomeStructure {
    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
        return 1
    }
}
enum SomeEnumeration {
    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
        return 6
    }
}
class SomeClass {
    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
        return 27
    }
    class var overrideableComputedTypeProperty: Int {
        return 107
    }
}
//  class   
class SubSomeClass: SomeClass {
    override class var overrideableComputedTypeProperty: Int {
        return 1077
    }
}
print(SomeClass.storedTypeProperty)
print(SomeClass.computedTypeProperty)
print(SomeClass.overrideableComputedTypeProperty)
print(SubSomeClass.overrideableComputedTypeProperty)
//Some value.
//27
//107
//1077