🔥 계산 속성
저장 속성 외에도 클래스, 구조체 그리고 열거형은 계산 속성(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는 (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))") // "square.origin is now at (10.0, 10.0)"를 출력합니다.
swift
이 예제는 기하학적 도형을 다루기 위한 세 개의 구조체를 정의하고 있어요.
Point
는 점의 x, y 좌표를 캡슐화합니다.Size
는width
와height
를 캡슐화하고요.Rect
는 원점(origin point)과 크기(size)로 사각형을 정의하네요.
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 선언
만약 계산 속성의 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) } } }
swift
단축 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) } } }
swift
getter에서 return
을 생략하는 것은 Functions With an Implicit Return에 설명된 대로 함수에서 return
을 생략하는 것과 동일한 규칙을 따릅니다.
읽기 전용 계산 속성
getter는 있지만 setter가 없는 계산 속성을 읽기 전용 계산 속성
라고 합니다. 읽기 전용 계산 속성은 항상 값을 반환하며, 점 문법을 통해 접근할 수 있지만 다른 값으로 설정할 수는 없어요.
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)") // "the volume of fourByFiveByTwo is 40.0"를 출력합니다.
swift
이 예제는 Cuboid
라는 새로운 구조체를 정의하는데, 이는 width
, height
, depth
속성을 가진 3D 직사각형 상자를 나타냅니다. 이 구조체는 또한 volume
이라는 읽기 전용 계산 속성을 가지고 있어요. 이는 cuboid의 현재 부피를 계산하고 반환하지요.
volume
을 설정 가능하게 만드는 것은 어떤 width
, height
, depth
값이 특정 volume
값에 사용되어야 하는지 모호하기 때문에 의미가 없어요. 그럼에도 불구하고 외부 사용자가 현재 계산된 부피를 알 수 있도록 Cuboid
가 읽기 전용 계산 속성을 제공하는 것은 유용하답니다.
이렇게 계산 속성은 실제로 값을 저장하지 않으면서도 다른 속성의 값에 기반하여 동적으로 계산된 값을 제공할 수 있게 해줍니다. 이는 코드의 가독성을 높이고 중복을 줄이는 데 큰 도움이 되지요. 계산 속성을 적절히 활용한다면 Swift 코드를 더욱 간결하고 표현력 있게 만들 수 있을 거예요!