7/26 TIL
헷갈리고도 헷갈리는 프로퍼티의 세계에 대해 공부한 걸 바탕으로 주저리주저리 읊어볼까 한다.
머리에 정립이 안되니 너무 헷갈려서.. 일단 읊어보면 이해되지 않을까?
Property
구조체와 클래스 내에서 변수와 상수를 프로퍼티라고 부른다.
이 프로퍼티는 우선 타입 프로퍼티랑 인스턴스 프로퍼티로 나뉜다.
(지금 말하는 이 두 프로퍼티들은 저장 프로퍼티의 특성을 띄는데 편의상 키워드는 생략하고 부르겠다.)
타입 프로퍼티와 인스턴스 프로퍼티
IceCream이라는 클래스가 있고
IceCream이라는 클래스 타입 내에 flavor라는 프로퍼티에 접근하고 싶다면 우리는 인스턴스를 생성해야 가능하다.
var myIceCream = IceCream()
myIceCream.flavor = "엄마는외계인"
var yourIceCream = IceCream()
yourIceCream.flavor = "사빠딸"
그리고 이렇게 각각의 인스턴스마다 서로 다른 값을 줄 수 있다.
이게 바로 인스턴스 프로퍼티다.
타입 프로퍼티는 인스턴스 프로퍼티와 다르게 클래스에서 바로 접근이 가능하다.
따라서 항상 초기값이 있어야 하고, 그렇기 때문에 어느 인스턴스에서든 그 생성 여부와 상관없이 그 값이 동일하다.
약간,,, 사람으로 치자면 본명(타입 프로퍼티)은 변하지 않지만, 별명(인스턴스 프로퍼티)은 여러개인 그런 바이브인 셈이다.
예시를 들자면,,, 만약 내가 개명을 해서 내 이름이 김루희에서 이말자가 되면 내 서류상 관련된 모든 이름은 이말자가 되는 거지만
내가 만약 다니던 회사의 닉네임이 루키에서 후리로 바뀌면 회사의 닉네임만 후리로 바뀌고 다른 곳에서는 여전히 다른 이름인 것이다.
타입/인스턴스 저장 프로퍼티
여기까지가 타입 프로퍼티와 인스턴스 프로퍼티에 대한 설명인데
그 중에서도 타입 "저장" 프로퍼티와 인스턴스 "저장" 프로퍼티에 대한 설명이다.
이 저장 프로퍼티들은 말 그래도 값을 저장하기 위해서 사용되는 프로퍼티들이다.
>> 인스턴스 저장 프로퍼티의 경우는 3가지가 있다.
1. var flavor = "뉴욕치즈케이크"
2. var flavor : String?
3. var flavor: String
init(flavor: String) {
self.flavor = flavor
}
차례대로
1. 선언과 동시에 초기화하는 경우
2. 옵셔널 값으로 초기화하는 경우 -> nil값 때문에 런타임에 오류 발생 위험이 있으니 조심해서 써야 한다.
3. 초기화 구문으로 초기화하는 경우
>> 지연 저장 프로퍼티 Lazy var
이름에서도 알 수 있듯이 저장 프로퍼티가 초기화되는 것을 지연시켜주는 것이다.
즉, 메모리에 올라가는 타이밍을 늦춰주는 것이다!!!!
- 옵션적인 상황이 있거나, 초반에 초기화하기 부담스러운 용량이나 시간일 때, 사용한다고 한다...
그래서 필요한 타이밍에 이 아이를 불러주면 그때 초기화가 된다. -
근데 lazy let은 불가능하다! 왜냐하면 초기화를 지연시킨다는 것은 곧,,, 초기값이 꼭 있다는 것이 아닌 것( = nil)을 말하는데..
let의 경우, 초기값을 인스턴스 생성도 전에 항상 갖고 있는 상태이기 때문이다. (값이 변하지 않기 때문에)
따라서, lazy와 var는 짝꿍임
>> 타입 저장 프로퍼티
인스턴스가 몇 개든 간에 타입 프로퍼티는 항상 값이 동일하다.
이 아이는 한 번 인스턴스를 생성하면 그 후로 끝이다.
(주저리주저리 썼지만 위에서 썼던 거랑 똑같음. 맞음. 위에 쓴 거가 타입 저장 프로퍼티니까;)
그럼 이와 별개로 연산 프로퍼티들이 존재한다.
연산 프로퍼티
저장도 했으니 연산도 해줘야지. 암요암요..
저장 프로퍼티와 다른 가장 큰 특징은 열거형, 구조체, 클래스 내에서 모두 사용할 수 있다는 것임
저장 프로퍼티는 열거형에서 못 쓰는데 말이지!!!!
열거형이 저장 프로퍼티가 안되고 연산 프로퍼티만 되는 이유가 뭘까.... 왜지? 왤까!
일단 쉽게 이해가 되는 선에서 먼저 생각하자면,,, 열거형은 초기화 구문이 없다.
구조체랑 클래스는 초기화 구문이 있는데 열거형은 초기화 구문이 없음.
그래서 인스턴스 저장 프로퍼티는 인스턴스 생성이 불가능해서 실격임
근데 타입 저장 프로퍼티는 선언할 때부터 초기값을 필수적으로 생성해주기 때문에 사용가능
그리고 연산 프로퍼티가 가능한 이유는 사용하지 않으면 메모리에 올라가지 않기 때문임 -> 아직 이해 안감..
연산 프로퍼티는 초기화 해줄 곳이 없다.
긍까,,, 눈으로 보기에.. = "초코맛" -> 이 공간이 없다.. 그러면 초기화해줄 곳이 없는데 어떤 걸로 연산을 하냐?
그건 다른 저장 프로퍼티의 값을 가지고 연산한다.
getter 접근자
getter는 매번 들어서 알지만 읽기 전용 프로퍼티다. 그렇다고 해서 let으로 선언하는 것은 아니다.
왜냐하면 안에 들어오는 저장 프로퍼티를 통해 들어온 값이 바뀔 수 있기 때문이다.
연산 프로퍼티가 없었다면 기존에는 인스턴스를 생성해 클래스를 초기화해서
let bmi = BMI(nickname: ~, weight: ~, height: ~)
bmi.weight / bmi.height / bmi.nickname ... 이런 식으로 하나하나의 값에 접근해야 했다면
근데 연산 프로퍼티가 있다면 구조체 내에서 알아서 계산을 하기 때문에 이렇게 해주면 된다. 개꿀?
print(bmi.BMIResult)
Setter 설정자
newValue를 통해서 값이 들어오고, get을 통해 값을 가져온다.
set을 통해 값을 넣어주고, get을 통해 값을 가져온다.
그래서 종종 코드 짤 때 프로퍼티의 속성 중에
var currentTitle: String? { get } 뭐.. 대강 이렇게 있다고 치면,, 이놈자식은.. 값 변경이 안되는 거다...
매번 get / set 부분이 어려웠는데.. Extension에서도 내가 써주고 있다는 것을 몰랐다....... 오호라..
이 아래 부분도 다마고치 예제에서 LV ~ 그 지점에 적용해봐야 할 것 같다. 우선 코드를 갈아엎어야 할 것 같다.
열거형에서 사용되는 것도 알게 모르게 되게 많았는데
디자인시스템에 적용한다고 되게 많이 쓰고 있었더라.
정리를 하였으나,, 결국은 코드에 직접 적용해보면서 써봐야 할 것 같다고 느꼈다.
찐막으로 진짜 걍 정리하면,
타입 저장 프로퍼티는 인스턴스 별로 값이 무조건 하나로 같고, 메모리에 올라가면 값이 변경되지 않는다. static~
인스턴스 저장 프로퍼티는 사용하기 위해서는 인스턴스를 생성해서 꼭 초기화를 해줘야 한다. 그래야만 접근 가능하고 인스턴스 별로 값이 다를 수 있다는 점...!
인스턴스 연산 프로퍼티는 저장할 공간이 없어 저장 프로퍼티를 통해 값을 연산하는데, set을 통해 값을 넣어주면 get을 통해 값을 가져온다더라.. 그리고 그 파라미터는 보통 newValue라고 한다더라... 타입 연산 프로퍼티는 거기에서 타입 저장 프로퍼티를 사용해서 한다더라~
열거형에서 저장 프로퍼티를 사용할 수 없는 건 초기화 구문이 없어서~
그리고,, 지연 저장 프로퍼티는 필요한 시점에 초기화를 해준다더라... 메모리에 올려주는 거가 늦는.. 그런 아이..
맞게 이해한 것인가.. 틀린 부분이 잇다면.. 댓글.. plz..
아!
그래서 고민 포인트는!!
이 각각의 프로퍼티를 언제 어떻게 잘 활용하냐는 것이다. 우선 인스턴스 저장 프로퍼지는 주구장창 쓰는 중이고, 타입 프로퍼티도 간혹가다 쓰는 중이다.
예를 들어, 문자열 틀리면 곤란한 경우에..?
지연 저장,, 레이지바도 써먹는 중이긴 하다..
그 외에 연산 프로퍼티는 언제 써야 할까?
적재적소에 잘 활용하고 싶다.
우선 당장은 수요일에는 다마고치를 뜯어고쳐 볼까 한다.. 내가 구조체를 잘못 잡았단 걸 깨달았고, 그 부분에 대해 연산 프로퍼티도 적용해보고 싶다..
후 대공사..; 진짜 거의 63층까지 다 짓고 나니까 거기에 유물 발견된 곳이라고 다시 건물 해체쇼하라는 것 같음;; 개킹
'⭐️ 개발 > iOS & Swift' 카테고리의 다른 글
[iOS] '처음으로' 돌아가는 코드 | SceneDelegate에서 분기처리해주는 코드 (0) | 2022.07.27 |
---|---|
[Swift] Property Observer - didSet / willSet (0) | 2022.07.27 |
[Swift] 타입 프로퍼티 왜 씀? (0) | 2022.07.21 |
[iOS] cell shadow + cornerRadius 같이 주는 방법 (0) | 2022.07.21 |
[iOS] Enum으로 코드 리팩토링 (0) | 2022.07.19 |