오늘은 속성 properties(프로퍼티)에 대해서 공부해보았다.
프로퍼티는 인스턴스 또는 타입의 부분인 저장된 값과 계산된 값에 접근한다. 값을 특정 클래스, 구조체, 또는 열거형을 연결한다.
프로퍼티는 저장, 지연, 계산, 타입, 속성 감시자 등이 존재한다.
# Stored Properties(저장 프로퍼티)
가장 간단한 형식의 저장 프로퍼티는 특정 클래스 또는 구조체의 인스턴스의 부분을 저장된 상수 또는 변수를 말한다. 저장 프로퍼티는 var
, let
을 쓸 수 있다.
# 특징
- 클래스/구조체의 틀에서 찍어낸 각 인스턴스가 가지는 고유의 데이터 저장 공간
- 객체의 초기화시 각 저장 속성은 반드시 값을 가져야 한다. 기본값 설정하거나 또는 생성자에서 설정 또는 옵셔널 타입으로 선언하여 nil을 초기값으로 갖는 것 가능하다.
- 열거형의 경우 따로 메모리 공간이 필요한 저장 속성(데이터)은 선언할 수 없다.
위와 같이 storedPropertis구조체
에서 생성 한 인스턴스를 변수로 선언한다면 variable
은 값이 변경되지만 상수인 constent
는 변경이 되지 않는 모습을 볼 수 있다. 그리고 만약 상수로 인스턴스를 생성한다면 아무리 변수인 variable
이라도 변경이 되지 않는 것을 볼 수 있으며, 이걸로 struct는 값 타입
이라는 걸 알 수 있게된다.
# Lazy stored properties(지연 저장 프로퍼티)
지연 저장 프로퍼티
는 처음 접근될 때 초기화가 되고 메모리 관리와 성능 최적화에 유리하다.
# 특징
- 구조체와 클래스에서만 사용 가능하다. (열거형 사용하지 못함)
- 해당 속성이 반드시 처음부터 초기화가 필요하지 않은 경우에 사용되며, 일반적으로 많은 메모리 공간을 차지하는 이미지 등에 초기화를 지연시킨다 -> 불필요한 성능저하나, 메모리 공간의 낭비를 줄일 수 있다.
- lazy var로만 선언가능 (lazy let은 불가) -> 인스턴스 초기화가 완료된 후에도 초기값이 없을 수 있으므로 지연 프로퍼티는 var 키워드를 사용하여 변수로 선언해야한다. 프로퍼티 상수는 초기화가 완료되기 전에 항상 값을 가지고 있어야 하므로 lazy로 선언할 수 없습니다.
- 생성자에서 초기화하지 않기 때문에 반드시 기본값이 필요 -> 기본값은 표현식의 어떤 형태는 return값만 일치하면 가능(함수 실행문, 계산식, 클로저 실행문 등)
# 사용하는 이점
- 메모리 공간의 낭비를 막을 수 있다.
- 지연 저장 속성으로 선언되는 속성이 다른 저장 속성을 이용해야 할 때 초기화 시점이 더 늦으므로, 먼저 초기화되는 저장 속성을 사용 가능하다.
ex) b변수는 초기화할때 a변수를 활용 가능
- 지연 프로퍼티는 인스턴스의 초기화가 완료될 때까지 값을 알 수 없는 외부 요인에 인해 초기값이 달라질 때 유용하다. 지연 프로퍼티는 프로퍼티의 초기값으로 필요할 때까지 수행하면 안되는 복잡하거나 계산 비용이 많이 드는 경우에도 유용하다.
# 예시코드
위의 코드는 ExpensiveResource 구조체
가 크기가 크거나 복잡한 경우라고 가정한 후, ResourceManager 클래스
에서 지연 저장 프로퍼티로 선언하였다. 그리고나서 ResourceManager
인스턴스를 생성하면 "ResourceManager initialized"가 출력이 된다. 그리고 지연 저장 프로퍼티로 저장해 놓았던 resource
에 접근하면 그때서 초기화가 되면서 "Heavy resourceManager initialized" 문구가 출력이 된다.
# Computed Properties(계산 프로퍼티)
저장 프로퍼티
외에도 클래스, 구조체, 그리고 열거형은 값을 실질적으로 저장하지 않는 계산 프로러티를 정의할 수 있다. 대신 다른 프로퍼티와 값을 간접적으로 조회하고 설정하는 getter와 옵셔널 setter를 제공한다.
# 특징
- 속성의 형태를 가진 실질적 메서드 (일반적으로 다른 저장 속성에 의존한 결과로 나오는 그런 방식의 메서드를 속성처럼 만든 것이다.)
- 메서드이기 때문에 인스턴스에 메모리공간이 할당되어 있지 않는다.
- var로만 선언 가능, 자료형까지 선언해야한다.(형식 추론 방식이 안되기 때문이다.)
- get블록만 선언하면 읽기전용 계산 속성이 된다.(필수 구현)
- set블록은 선택적으로 구현할 수 있다.(set만 구현하는 것은 불가능하다.)
- Set블록에서 기본 파라미터 newValue가 제공된다.(직접 파라미터 이름 설정도 가능하다.)
# 사용하는 이유
- 값을 저장하지 않고 다른 속성이나 상태를 기반으로 동적으로 계산된 값을 제공한다. 그렇기에 저장된 값과 실제 사용되는 값 사이의 불일치를 방지할 수 있다고 한다.
- 동일한 정보를 여러 곳에 저장하기보다는 필요한 시점에 계산하여 제공함으로써 중복 데이터 관리를 줄일 수 있다.
- 값이 자동으로 계산되어 업데이트되므로, 수동으로 값 변경을 관리할 필요가 없어 코드를 간결하고 유지 보수하기 쉽다.
즉, 저장 공간을 절약하면서도 특정 값을 동적으로 계산해야 할 때 유용하며 특히 중복데이터 관리, 의존 관계가 있는 데이터 관리, 데이터 변환이 필요한 상황에서 사용하기 좋다. 그렇게 이용하면 코드의 일관성과 유지보수를 유용하게 할 수 있다고 한다.
# 계산 속성을 사용하는 상황
- 데이터 변환이 필요한 경우 : 외부 데이터 형식과 내부 로직에 맞게 변환할 때 사용한다. 예를 들어 시간데이터를 처리할 때 초 단위를 시간, 분으로 변환하여 보여줄 수 있다.
- 의존 관계가 있는 값이 자주 변경되는 경우 : 총 금액이 아이템의 개수와 단가에 따라 달라진다면 계산 속성으로 총 금액을 제공하여 필요한 순간에만 계산되도록 할 수 있다.
# 예시 코드
BMI를 계산해주도록 선언한 계산 프로퍼티로 타입 추론이 되지 않기에 미리 Double
이라고 선언을 해주어야하고, get
을 통해 값을 계산을 해 반환해준다. set
은 필수 구현은 아니지만 만약에 내가 BMI 값을 알고 그 값을 이용해 weight를 알고싶은 경우와 같이 사용을 할 수가 있다.
계산기 시작이 아직이군요.