프로퍼티 (Properties) - 계산된 프로퍼티 (Computed Properties)

00yhsp·2024년 4월 23일

저장된 프로퍼티 외에도 클래스, 구조체, 그리고 열거형은 값을 실질적으로 저장하지 않는 계산된 프로퍼티 (computed properties) 를 정의할 수 있다. 대신 다른 프로퍼티와 값을 간접적으로 조회하고 설정하는 getter와 옵셔널 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
// initialSquareCenter is at (5.0, 5.0)
square.center = Point(x: 15.0, y: 15.0)
print("square.origin is now at (\(square.origin.x), \(square.origin.y))")
// Prints "square.origin is now at (10.0, 10.0)"

이 예제는 기하학적 모양과 작업을 위해 3개의 구조체를 정의한다:

Point 는 x, y 좌표의 위치를 캡슐화한다.

Size는 width 와 height를 캡슐화한다.

Rect는 원점과 크기로 사각형을 정의한다.

Rect 구조체는 center 라는 계산된 프로퍼티를 제공한다. Rect 에 현재 중앙 위치는 항상 origin 과 size 로 계산될 수 있고 명시적으로 Point 값으로 저장할 필요가 없다. 대신에 Rect 는 center 라는 계산된 변수를 위한 getter와 setter를 정의하고 실제 저장된 프로퍼티처럼 사각형의 center를 동작하도록 한다.

위의 예제는 square 라는 새로운 Rect 변수를 생성한다. square 변수는 (0, 0) 의 원점으로 너비와 높이가 10 으로 초기화된다. 이 사각형은 아래의 다이어그램에서 밝은 초록색 사각형으로 표현된다.

square 변수의 center 프로퍼티는 점 구문 (square.center)으로 접근되고 center 에 대한 getter를 호출하여 현재 프로퍼티 값을 조회한다. 존재하는 값을 반환하기 보다 getter는 실질적으로 사각형의 중심을 나타내는 새로운 Point 를 계산하고 반환한다. 위에서 볼 수 있듯이 getter는 (5, 5) 의 중심점을 반환한다.

아래 다이어그램의 어두운 초록색 사각형처럼 center 프로퍼티는 (15, 15)의 새로운 값으로 설정되어 새로운 위치로 사각형이 위와 우측으로 이동한다. center 프로퍼티 설정은 center 의 setter를 호출하고 origin 프로퍼티에 저장된 x 와 y 값을 변경하고 사각형을 새로운 위치로 이동시킨다.

짧은 Setter 선언 (Shorthand Setter Declaration)

계산된 프로퍼티의 setter가 새로운 값을 설정하는데 이름을 정의하지 않았다면 newValue 라는 기본 이름이 사용된다. 다음은 이러한 짧은 표현의 이점을 가지는 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 선언 (Shorthand Getter Declaration)

getter의 전체 본문이 단일 표현식이라면 getter는 암시적으로 표현식을 반환한다. 다음은 짧은 getter와 setter의 이점을 가진 Rect 구조체를 나타낸다:

struct CompactRect {
    var origin = Point()
    var size = Size()
    var center: Point {
        get {
            Point(x: origin.x + (size.width / 2),
                  y: origin.y + (size.height / 2))
        }
        set {
            origin.x = newValue.x - (size.width / 2)
            origin.y = newValue.y - (size.height / 2)
        }
    }
}

getter에서 생략한 return은 함수의 return 생략 규칙과 동일하다.

읽기전용 계산된 프로퍼티 (Read-Only Computed Properties)

setter가 없고 getter만 있는 계산된 프로퍼티는 읽기전용 계산된 프로퍼티 (read-only computed property) 라고 한다. 읽기전용 계산된 프로퍼티는 항상 값을 반환하고 점 구문으로 접근할 수 있지만 다른 값을 설정할 수 없다.

Note
값이 고정되어 있지 않기 때문에 읽기전용 계산된 프로퍼티를 포함하여 계산된 프로퍼티는 var 키워드를 포함하는 프로퍼티 변수로 선언되어야 한다. let 키워드는 인스턴스 초기화의 부분으로 한번 설정되면 값을 변경할 수 없음을 나타내기 위해 오직 프로퍼티 상수에서만 사용된다.

get 키워드와 그것의 중괄호를 삭제하고 읽기전용 계산된 프로퍼티를 간편하게 선언할 수 있다:

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)")
// Prints "the volume of fourByFiveByTwo is 40.0"

이 예제는 width, height, 그리고 depth 프로퍼티를 가지는 3D 사각형 박스를 나타내는 Cuboid 라는 새로운 구조체를 정의한다. 이 구조체는 직육면체의 현재 부피를 계산하고 반환하는 volume 이라는 읽기 전용 계산된 프로퍼티를 가지고 있다. 특정 volume 값에 width, height, 그리고 depth 의 어떤값을 사용하여야 하는지 모호하므로 volume 을 설정하는 것은 의미가 없다. 그럼에도 불구하고 현재 계산된 부피를 알 수 있도록 외부에 읽기전용 계산된 프로퍼티로 제공되는 Cuboid는 유용하다.

profile
iOS Dev

0개의 댓글