Properties

  • 프로퍼티는 클래스, 구조체, 열거형과 관련한 값입니다.
  • 프로퍼티의 종류에는 두가지가 있습니다.
    • 저장 프로퍼티(Stored Properties)
      • 말 그대로 값을 저장하고 있는 프로퍼티입니다.
      • 클래스, 구조체, 열거형에서 모두 사용이 가능합니다.
    • 계산된 프로퍼티(Computed Properties)
      • 값을 저장하지 않고 특정하게 계산한 값을 반환해주는 프로퍼티입니다.
      • 클래스, 구조체에서만 사용이 가능합니다.
      • 추가로 프로퍼티 옵저버를 정의해서 값이 변할 때마다 모니터링 할 수 있습니다.
  • 초기화 방법
    • 타입을 옵셔널로 설정해줌
    • 프로퍼티 선언과 동시에 값을 넣어줘 초기화 시켜줌
    • 초기화 구문을 사용하여 프로퍼티 초기화(init문 사용)

저장 프로퍼티(Stored Properties)

  • 저장 프로퍼티는 단순히 값을 저장하고 있는 프로퍼티입니다.
  • 값이 변하지 않는 상수를 선언할 때는 let
  • 값으 변하는 변수를 선언할 때는 var

  • lengh는 let으로 선언 되어 있기 때문에 값을 변경해줄 수 없습니다.
  • 그러나 struct가 아닌 class는 참조 타입이기 때문에 let이어도 값을 변경해줄 수 있습니다.

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

  • 지연 저장 프로퍼티는 값이 처음으로 사용 되기 전에는 계산되지 않는 프로퍼티입니다.
  • 지연 저장 프로퍼티를 선언하기 위해선 lazy 키워드를 붙혀주면 됩니다.
    • 지연 프로퍼티는 반드시 var로 선언해줘야 합니다.
    • 상수는 초기화 되기 전에 항상 같은 값을 같는 프로퍼티지만 지연 프로퍼티는 사용되기 전까진 값을 갖지 않기 때문입니다. 
  • 지연 저장 프로퍼티는 특정 요소에 의존적이기 떄문에 그 요소가 끝나기 전에는 값을 알지 못하는 경우에 유용합니다.
  • 또한 복잡한 계산이나 부하가 많이 걸리는 작업을 지연 프로퍼티를 사용해주면 실제 사용되기 전까지 실행되지 않아 인스턴스의 초기화 시점에 복잡한 계산을 피해줄 수 있습니다.

  • 예제를 보면 Datamanger의 importer이 지연 저장 프로퍼티로 선언되어 있습니다.
  • manager.data.append가 실행됐을 때는 importer 프로퍼티에 접근되지 않아 importer 인스턴스가 생성되지 않았습니다.
  • 그러나 맨 밑 print문에서 manager.importer.filename으로 importer 프로퍼티에 접근하는 순간 Importer 프로퍼티가 생성됩니다.
  • static으로 선언하면 lazy 키워드를 붙이지 않아도 자동으로 lazy로 동작합니다.!

계산 프로퍼티(Computed Properties)

  • 클래스, 구조체, 열거형에서 선언할 수 있는 프로퍼티
  • 실제 값을 저장하고 있는 것이 아니라 getter, optional한 setter를 제공해 값을 탐색하고 간접적으로 다른 프로퍼티 값을 설정할 수 있는 방법을 제공해줍니다.
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
square.center = Point(x: 15.0, y: 15.0)
print("square.origin is now at (\(square.origin.x), \(square.origin.y))")
// "square.origin is now at (10.0, 10.0)" 출력
  • 위 코드르 ㄹ보면 center라는 계산된 프로퍼티를 제공합니다.
  • 직접 값을 갖고 있는 것이 아닌 다른 좌표와 크기 프로퍼티들을 적절히 연산해서 구해줄 수 있습니다.
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)
        }
    }
}
  • 위의 코드처럼 newCenter같이 쓰지 않고 newValue라는 default한 이름을 사용할 수도 있습니다.
struct Cuboid {
    var width = 0.0, height = 0.0, depth = 0.0
    var volume: Double {
        return width * height * depth
    }
}
let fourByFiveByTwo = Cuboid(width: 4.0, height: 5.0, depth: 2.0)
print("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)")
// "the volume of fourByFiveByTwo is 40.0" 출력
  • 읽기 전용 Computed Property도 있습니다.
  • 반드시 반환 값을 제공하고 다른 값을 지정해줄 수는 없는 프로퍼티입니다.
    • let이 아닌 var로 선언해줘야 합니다.
    • 계산 값에 따라 값이 변할 수도 있기 때문입니다.

정리해보자면

  • get, set
    • 프로퍼티 초기화 시 값을 검증해줌
    • 이유: private한 프로퍼티를 사용해주기 위해
    • 저장 프로퍼티는 메모리에 올라간다.
    • 연산 프로퍼티는 저장프로퍼티를 활용하여 원하는 값을 반환하는 용도로 주로 사용하게 됩니다.
  • get
    • 읽기 전용 권한으로 구현할 때 사용합니다.
    • 연산 프로퍼티가 다른 프로퍼티 값을 연산 처리하여 간접적으로 값을 제공할 때 프로퍼티 값을 참고하기 위해 return을 사용하여 반환
  • set
    • 쓰기 전용 권한으로 구현할 때 사용합니다.
    • 연산 프로퍼티 값을 할당하거나 변경하고자 할 때 실행되는 구문/연산 프로퍼티는 값 자체를 저장하지 않기 떄문에 이때 할당되는 값입니다.
    • 읽기, 쓰기 모두 사용하고 싶다? -> get, set 모두 사용해주면 됩니다.
  • newValue
    • set 메서드 내부에서 전달 받는 인자의 관용적 표현입니다.
    • 네이밍은 변경해줄 수 있습니다.

Property Observers

  • 프로퍼티에는 값이 set 될 때마다 이벤트를 감지할 수 있는 옵저버를 제공합니다.
  • 새값이 이전값과 같더라도 항상 호출 됩니다.
    • 이 프로퍼티 옵저버는 lazy var(지연 저장) 프로퍼티에서는 사용이 불가능합니다.
  • 종류
    • willSet: 값이 저장되기 바로 직전에 호출됨
    • didSet: 값이 저장되고 난 직후에 호출됨

  • 위의 출력화면을 보면 bmi.BMIResult에서 값을 넣어줄 때 willSet이 출력되고
  • 값이 바뀌고 난 후에 didSet이 출력되는 것을 볼 수 있습니다.
  • newValue에 새로 들어가는 값 "올라프" oldValue에 "고래밥"이 들어가는 것을 확인해줄 수 있습니다.

+ Recent posts