swift

Properties

motosw3600 2021. 12. 8. 22:47

property(프로퍼티)

크게 5가지로 구성

1. 저장 프로퍼티(Stored Properties)

2. 지연 저장 프로퍼티(Lazy Stroed Properties)

3. 연산 프로퍼티(Computed Properties)

4. 프로퍼티 감시자(Property Observers)

5. 타입 프로퍼티(Type Properties)

 


1. 저장 프로퍼티(Stored Properties)

가장 단순한 개념으로 클래스 또는 struct의 인스턴스와 연관된 값을 저장하는 프로퍼티

class TestProperty{
    var a: Int // Stored Property
    var b: Int // Stored Property
}

 


2. 지연 저장 프로퍼티(Lazy Stored Properties)

expression : lazy

호출이 있어야 값이 초기화 된다. 그전까진 생성되지 않은 상태

주로 복잡한 클래스나 struct를 구현할 때 많이 사용된다.

예를 들어 클래스 인스턴스의 저장 프로퍼티로 다른 클래스 인스턴스나 구조체 인스터스가 할당되어야 할 때

※ 상수는 인스턴스가 완전히 생성되기 전에 초기화 되어야하므로 필요할 때 값을 할당하는 지연 저장 프로퍼티에는 맞지 않는다.

장점 : 불필요한 저장공간 낭비 줄일 수 있다.

struct SubLazy {
  var n: Int = 0
}

class TestLazy {
  lazy var value: SubLazy = SubLazy()
  let val: Int

  init(name: Int) {
      self.val = val
  }
}
//TestLazy 객체 생성 (SubLazy 객체는 생성되지 않은 상태)
let lazy: TestLazy = TestLazy(val: 10)

//lazy한 value프로퍼티로 처음 접근할 때 value 프로퍼티의 SubLazy생성
print(lazy.value)

 


3. 연산 프로퍼티(Computed Properties)

실제 값을 저장하는 프로퍼티가 아니라, 특정 상태에 따른 값을 연산하는 프로퍼티

인스턴스 값을 반환하는 getter나 프로퍼티 값을 설정하는 setter 기능 수행 가능

# 왜 연산 프로퍼티를 쓰는가?

메소드로 구현할 수도 있지만 getter, setter에 대한 메소드 따로 만들어야함

가독성이 떨어질 수 있어서 연산 프로퍼티로 작성하면 더 간편하고 직관적

※ get만 써서 읽기전용은 되지만 쓰기전용은 불가능(메소드로는 가능, 연산 프로퍼티로는 불가)

struct Hex {
  var decimal: Int?
  var hexString: String? {
    get {
      if let decimal = self.decimal {
        return String(decimal, radix: 16)
      } else {
        return nil
      }
    }
    set { 
      if let newValue = newValue { // 관용적으로 newValue로 매개변수 대체 가능
        self.decimal = Int(newValue, radix: 16)
      } else {
        self.decimal = nil
      }
    }
  }
}

var hex = Hex()
hex.decimal = 10
hex.hexString // "a"

hex.hexString = "b"
hex.decimal // 11

 


4. 프로퍼티 감시자(Property Observers)

프로퍼티 감시자를 사용하면 프로퍼티의 값이 변경됨에 따라 액션 호출 가능

프로퍼티의 값이 새로 할당될 때마다 호출되고 변경되는 값이 현재 값과 같더라도 호출

지연 저장 프로퍼티에서 사용 불가, 저장 프로퍼티에서만 적용 가능

willSet : 프로퍼티의 값이 변경되기 직전에 호출(newvalue는 변경될 값)

didSet : 프로퍼티 값이 변경된 직후 호출(oldValue는 변경되기 전의 값)

class Account {
    var credit: Int = 0 {
        willSet {
            print("잔액이 \(credit)에서 \(newValue)원으로 변경될 예정입니다.")
        }
        
        didSet {
            print("잔액이 \(oldValue)에서 \(credit)으로 변경되었습니다.")
        }
    }
}

let myAccount: Account = Account()
myAccount.credit = 1000

//잔액이 0에서 1000원으로 변경될 예정입니다.
//잔액이 0에서 1000으로 변경되었습니다.

 


5. 타입 프로퍼티(Type Properties)

각각의 인스턴스가 아닌 타입 자체에 속하게 되는 프로퍼티

타입 프로퍼티는 타입 자체에 영향을 미치는 프로퍼티이고 인스턴스의 생성 여부와 관련없이 타입 프로퍼티의 값은 하나이다.

타입 프로퍼티를 선언을 위해서는 static 키워드를 사용

 

staticclass 이렇게 2가지 형태로 타입 프로퍼티를 선언할 수 있는데 두 가지 경우의 차이는서브클래스에서 overriding가능 여부

인스턴스 프로퍼티와는 다르게 타입 프로퍼티는 항상 초기값을 지정해서 사용해야 합니다. 왜냐하면 타입 자체에는 초기자(Initializer)가 없어 초기화 할 곳이 없기 때문입니다.

# 언제 타입 프로퍼티쓰는가?

그타입의 모든 인스턴스가 공통으로 사용되는값, 모든 인스턴스에서 공통으로 접근하고 값을 변경하는 변수등을 정의할 때

lass Aclass {

    static var typeProperty: Int = 0
    
    var instanceProperty: Int = 0 {
        didSet {
            Aclass.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)  // 200
print(Aclass.typeComputedProperty)  // 200

 

출처 : https://docs.swift.org/swift-book/LanguageGuide/TheBasics.html

'swift' 카테고리의 다른 글

Layout Update Method  (0) 2021.12.09
KVC, KVO  (0) 2021.12.08
ARC(Auto Reference Count)  (0) 2021.12.07
Strong, Weak, Unowned, 순환참조  (0) 2021.12.07
Swift언어의 특징  (0) 2021.12.07