티스토리 뷰

프로퍼티는 클래스, 구조체, 열거형 내부에 선언되어 호출되는 상수나 변수를 의미한다. 

 

프로퍼티의 종류에는 Stored Properties 와 Computed Properties가 있는데, stored는 말 그대로 값을 저장하고 있는 프로퍼티이고, Computed는 값을 저장하고 있지 않고 특정하게 계산한 값을 반환해주는 프로퍼티이다. Computed 는 클래스, 구조체, 열거형에 모두 사용이 가능하지만 Stored는 클래스와 구조체 내에서만 사용이 가능하다.

 

추가로 프로퍼티 옵저버를 정의하여 값이 변할 때마다 모니터링할 수 있다. 

 

1. Stored Properties

 

저장 프로퍼티는 앞서 봐왔던 예제와 동일하게 단순히 값을 저장하고 있는 프로퍼티이다. 

struct FixedLengthRange {
    var firstValue: Int
    let length: Int
}
var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3)
// 범위 값은 0, 1, 2 입니다.
rangeOfThreeItems.firstValue = 6
// 범위 값은 6, 7, 8 입니다.

 

아래와 같이 구조체를 상수로 선언하면, 그 구조체 인스턴스의 프로퍼티는 변경할 수 없다.

 

lazy 키워드를 사용하여 값이 처음으로 "사용"되기 전까지는 계산하지 않는 지연 저장 프로퍼티를 구현할 수 있다.

class DataImporter {
    /*
        DataImporter는 외부 파일에서 데이터를 가져오는 클래스입니다.
         이 클래스는 초기화 하는데 매우 많은 시간이 소요된다고 가정하겠습니다.
     */
    var filename = "data.txt"
    // 데이터를 가져오는 기능의 구현이 이 부분에 구현돼 있다고 가정
}

class DataManager {
    lazy var importer = DataImporter()
    var data = [String]()
    // 데이터를 관리하는 기능이 이 부분에 구현돼 있다고 가정
}

let manager = DataManager()
manager.data.append("Some data")
manager.data.append("Some more data")
// DataImporter 인스턴스는 이 시점에 생성돼 있지 않습니다.

print(manager.importer.filename)
// the DataImporter 인스턴스가 생성되었습니다.
// "data.txt" 파일을 출력합니다.

2. Computed Propeties

계산된 프로퍼티는 실제 값을 저장하고 있는 것이 아니라, 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))")

위 예제에서 확인이 가능하듯, center라는 computed Properties를 에 Point 생성자를 호출하여 대입하면 center생성자가 가지고 있는 set 메서드가 실행되어 origin 값을 재설정한다.

 

위 예제에서는  setter의 인자 이름을 set(newCenter)로 명시했지만, 아래와 같이 이를 지정하지 않고 newValue로 사용이 가능하다.

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를 제공하지 않는 계산된 프로퍼티를 읽기 전용(Read-Only) 계산된 프로퍼티라고 한다.

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" 출력

3. 프로퍼티 옵저버

프로퍼티에는 새 값이 설정될 때마다 이 이벤트를 감지할 수 있는 옵저버를 제공한다.

이 프로퍼티 옵저버는 새 값이 이전 값과 같더라도 항상 호출하며, 지연 저장 프로퍼티는 사용할 수 없다.

 

계산된 프로퍼티는 setter에서 값의 변화를 감지할 수 있기 때문에 따로 옵저버를 정의할 필요는 없다.

 

- willSet: 값이 저장되기 바로 직전에 호출됨, setter 의 기본 파라미터 명: newValue

- didSet: 새 값이 저장되고 난 직후에 호출됨, setter의 기본 파라미터 명: oldValue

 

class StepCounter {
    var totalSteps: Int = 0 {
        willSet(newTotalSteps) {
            print("About to set totalSteps to \(newTotalSteps)")
        }
        didSet {
            if totalSteps > oldValue  {
                print("Added \(totalSteps - oldValue) steps")
            }
        }
    }
}
let stepCounter = StepCounter()
stepCounter.totalSteps = 200
// About to set totalSteps to 200
// Added 200 steps
stepCounter.totalSteps = 360
// About to set totalSteps to 360
// Added 160 steps
stepCounter.totalSteps = 896
// About to set totalSteps to 896
// Added 536 steps

 

 

Comments