[オブジェクト向けプログラミングとswift]プロパティ


propertyはクラス、構造体、列挙型などに関連する値を表し、メソッドは特定のタイプに関連する関数を表す.
💡 ツールバーの
番組は大きく3つに分けられます.
  • 記憶属性
  • 計算属性
  • タイプ属性
  • ストアド・プロシージャは、インスタンスの変数または定数を表します.構造体とクラスでのみ使用できます.
    演算プログラムは、値を格納するのではなく、特定の演算を実行した結果値を表します.クラス、構造体、列挙型に使用できます.
    この2つのpropertyは、特定のタイプのインスタンスを表すが、タイプpropertyと呼ばれる特定のタイプのpropertyも存在する.
    実際にプログラムを作成するときに使用するインスタンス変数は、ストレージ・プロシージャであってもよく、クラス変数はタイプ・プロシージャであってもよい.
    ▼▼記憶属性
    構造体またはクラスインスタンスに関連付けられた値を格納する最も簡単な概念のプログラム.
    varキーワードを使用して変数ストレージ・プロシージャを表し、letキーワードを使用して定数ストレージ・プロシージャを表します.
    ストアド・プロシージャの宣言とインスタンスの初期化方法は次のとおりです.
    struct CoordinatePoint {
        var x: Int
        var y: Int
    }
    
    let myPoint: CoordinatePoint = CoordinatePoint(x: 2, y: 4)
    
    class Position {
        var point: CoordinatePoint
        let name: String
    }
    
    このように構造体とクラスを定義するとどうなりますか?
    構造体は基本的にストアド・プロシージャをパラメータとする頭文字Liserを提供しますが、クラスはそうではありませんので、エラーが放出されます.
    Class 'Position' has no initializers
    したがって、完全なコードは次のようになります.
    struct CoordinatePoint {
        var x: Int
        var y: Int
    }
    
    let myPoint: CoordinatePoint = CoordinatePoint(x: 2, y: 4)
    
    class Position {
        var point: CoordinatePoint	// 변수 저장 프로퍼티
        let name: String	// 상수 저장 프로퍼티
        
        // 프로퍼티 기본값을 설정해주지 않았기 때문에 이니셜라이저를 따로 정의
        init(name: String, currentPoint: CoordinatePoint) {
            self.name = name
            self.point = currentPoint
        }
    }
    
    // 사용자 정의 이니셜라이저 호출
    let myPosition: Position = Position(name: "silverCastle", currentPoint: myPoint)
    
    ただし、クラスのストレージ中に初期値を設定しておく場合は、カスタムアルファベットログインを個別に実施する必要はありません.
    インスタンスを作成するときに、初期値をアルファベットタグで送信する必要があるのはなぜですか?
    つまり、非公開の値として宣言されるため、値が必要になります.
    もし、非期待値として宣言するのではなく、期待値として宣言するとしたら?
    初期値を指定する必要はありません.
    以下に,傍観者の使用とユーザ定義の頭文字liserを適切に混合する方法を示す.
    struct CoordinatePoint {
        var x: Int
        var y: Int
    }
    
    class Position {
        var point: CoordinatePoint?
        let name: String
        
        init(name: String) {
            self.name = name
        }
    }
    
    // 이름은 옵셔널이 아닌 값이기 때문에 반드시 값을 넣어야 한다.
    let myPosition: Position = Position(name: "silverCastle")
    
    // 위치를 알게되면 그 때 위치 값을 할당해준다.
    myPosition.point = CoordinatePoint(x: 2, y: 4)
    ▼▼遅延記憶プロパティ
    「lazy」という言葉は、怠け者でのんびりした貯蔵番組を意味します.すなわち,必要に応じて遅延し,必要に応じて値を割り当てる.lazyキーを使用します.
    遅延ストレージ・プロトコルは、主に複雑なクラスまたは構造体を実装するために使用されます.一度にストレージ・プロトコルとしてインスタンスを作成する必要がある場合、またはすべてのストレージ・プロトコルを使用する必要がない場合は、遅延ストレージ・プロトコルを使用できます.
    これにより、不要なパフォーマンスの低下やスペースの浪費を減らすことができます.
    遅延ストレージ・プロシージャを宣言する方法は、次のとおりです.
    struct CoordinatePoint {
        var x: Int = 0
        var y: Int = 0
    }
    
    class Position {
        lazy var point: CoordinatePoint = CoordinatePoint()
        let name: String
        
        init(name: String) {
            self.name = name
        }
    }
    
    let myPosition: Position = Position(name: "silverCastle")
    
    // 필요한 시점인 지금, point 프로퍼티의 CoordinatePoint가 생성된다.
    print(myPosition.point)
    
    結果
    CoordinatePoint(x: 0, y: 0)
    
    ▼▼▼計算属性
    実際の値を格納するプログラムではなく、特定の状態に基づいて値を計算するプログラムです.
    インスタンス内/外部値を計算することによって、適切な値を返すアクセス者(getter)ロールと隠された内部Property値を間接的に設定する設定器
    (setter)の役割を果たすこともできます.
    なぜ計算プログラムを使わなければならないのか疑問に思うかもしれませんが、次を見てみましょう.
    メソッドの場合
    struct CoordinatePoint {
        var x: Int
        var y: Int
        
        // 대칭점을 구하는 메서드 - 접근자
        // Self는 타입 자기 자신을 의미, CoordinatePoint를 써도 무방
        func oppositePoint() -> Self {
            return CoordinatePoint(x: -x, y: -y)
        }
        
        // 대칭점을 설정하는 메서드 - 설정자
        mutating func setOppositePoint(_ opposite: CoordinatePoint) {
            x = -opposite.x
            y = -opposite.y
        }
    }
    
    var myPosition: CoordinatePoint = CoordinatePoint(x: 2, y: 4)
    
    print(myPosition)
    
    print(myPosition.oppositePoint())
    
    myPosition.setOppositePoint(CoordinatePoint(x: 20, y: 40))
    
    print(myPosition)
    計算プログラムの場合
    struct CoordinatePoint {
        var x: Int
        var y: Int
        
        var oppositePoint: CoordinatePoint {
            // 접근자
            get {
                return CoordinatePoint(x: -x, y: -y)
            }
            
            // 설정자
            set(opposite) {
                x = -opposite.x
                y = -opposite.y
            }
        }
        
    }
    
    var myPosition: CoordinatePoint = CoordinatePoint(x: 2, y: 4)
    
    print(myPosition)
    
    print(myPosition.oppositePoint)
    
    myPosition.oppositePoint = CoordinatePoint(x: 20, y: 40)
    
    print(myPosition)
    
    どうですか.コンピューティング・プログラムを使用すると、アクセス者と設定者が1つのプログラムに集約され、他のプログラマはプログラムの役割をより明確に理解できます.
    ▼▼▼プロパティモニター
    property値の変化を監視し、property値の変化に応じて適切な操作を行うことができます.変更した値が現在の値と同じであっても、propertyに新しい値を割り当てるたびに呼び出されることを覚えておいてください.
    didSetメソッドには、propertyの値が変更される前にwillSetメソッドを呼び出し、propertyの値が変更された後にdidSetメソッドを呼び出す方法があります.
    各メソッドにはパラメータがあります.willSetはpropertyが変更する値で、didSetはpropertyが変更する前の値です.
    パラメータ名を指定しない場合、willSetのパラメータ名はnewValue、didSetのパラメータ名はoldValueです.
    ストアド・プロシージャでプロシージャ・モニタを実装するコードは、次のとおりです.
    class Account {
        var credit: Int = 0{
            willSet {
                print("잔액이 \(credit)원에서 \(newValue)원으로 변경될 예정입니다.")
            }
            
            didSet {
                print("잔액이 \(oldValue)원에서 \(credit)원으로 변경되었습니다.")
            }
        }
    }
    
    let myAccount: Account = Account()
    
    myAccount.credit = 100000
    
    結果
    잔액이 0원에서 100000원으로 변경될 예정입니다.
    잔액이 0원에서 100000원으로 변경되었습니다.
    
    ▼▼グローバル変数とゾーン変数
    前述した演算プログラムおよびプログラムモニタは、プログラムに限らず、グローバル変数および領域変数に使用できます.
    ▼▼▼タイプ属性
    これまで知られてきたPropertyの概念は、各インスタンスのタイプ自体に属するPropertyではなく、タイプを定義し、そのタイプのインスタンスを作成するときに使用できるインスタンスPropertyです.
    インスタンスを作成するかどうかにかかわらず、タイプpropertyの値は1つの値であり、タイプ内のすべてのインスタンスで共通に使用される値と、すべてのインスタンスの共通アクセスと値を変更できる変数を定義するときに便利です.
    確認タイプpropertyとインスタンスpropertyの違いのコードは次のとおりです.
    class AClass {
        
        // 저장 타입 프로퍼티
        static var typeProperty: Int = 0
        
        // 저장 인스턴스 프로퍼티
        var instanceProperty: Int = 0 {
            didSet {
                Self.typeProperty = instanceProperty + 100
            }
        }
        
        // 연산 타입 프로퍼티
        static var typeComputedProperty: Int {
            get {
                return typeProperty
            }
            set {
                typeProperty = newValue
            }
        }
    }
    
    AClass.typeProperty = 123
    
    let classInstance: AClass = AClass()
    classInstance.instanceProperty = 100
    
    print(AClass.typeProperty)
    print(AClass.typeComputedProperty)
    
    ▼▼▼キーパス
    関数のようにプログラムの位置だけを参照することができます.これがキーパスを利用する方法です.
    鍵パスを使用して、特定のタイプのどのproperty値を間接的に指すかを事前に指定できます.
    検証鍵パスタイプのコードは次のとおりです.
    class Person {
        var name: String
        
        init(name: String) {
            self.name = name
        }
    }
    
    struct Info {
        var name: String
        var age: Int
    }
    
    print(type(of: \Person.name))
    print(type(of: \Info.name))
    
    結果
    ReferenceWritableKeyPath<Person, String>
    WritableKeyPath<Info, String>