-
Swift - Value type vs Reference typeProgramming/Swift 2021. 10. 23. 09:35
안녕하세요! Beepeach입니다 :)
오늘은 structure와 class의 가장 큰 차이점인 value type(값 타입)과 reference type(참조 타입)에 대해서 공부해보겠습니다!
단어가 생소해서 어려워 보일 수 있지만 사실 별거 아닙니다! 그럼 시작해보겠습니다.
Value Type (값 타입)
Structrue(구조체)와 Enumeration(열거형)은 값 타입입니다.
ValueType은 값이 상수나 변수에 할당이 될 때 또는 함수로 전달이 될 때 값이 복사가 됩니다.
가장 핵심은 '값이 복사가 된다'입니다.
이게 무슨말이지?? 할 수 있지만 사실 지금까지 계속 사용해왔습니다.
Int, Double, Bool, String, Array, Dictionary 등 모든 Swift basic type이 모두 값 타입이기 때문입니다.
해상도 구조체를 만들었습니다.
그리고 1920X1080 해상도를 가진 hd 인스턴스를 생성했습니다.
그리고 cinema라는 변수에 hd 인스턴스를 할당했습니다.
그럼 구조체는 값타입이기때문에 프로퍼티 값들이 복사됩니다.
hd.width와 cinema.width를 확인해보면 값이 같은 것을 확인할 수 있습니다.
여기서 이제 cinema의 width를 한 번 수정해보겠습니다.
cinema.width에 2048을 할당했습니다.
그럼 당연히 cinema.width는 이제 2048이겠죠??
그럼 hd.width의 값은??
cinema.width를 2048로 바꾼거지 hd.width를 2048로 바꾼 게 아니니까 당연히 1920이 나오겠죠???
네 지금까지 우리가 사용해오던것들은 다 이런 식으로 동작했습니다.
이렇게 되는 이유는 값을 복사하기때문에 cinema.width에는 hd.width의 값이 복사되어 저장이 되고
cinema.height에는 hd.height의 값이 복사되어 저장되기 때문입니다.
값이 복사되어 저장됐으니 이제 이 값을 바꿔도 원본의 값은 그대로 유지할 수 있는 거죠!
그럼 이제 reference type을 보도록 하겠습니다.
Reference Type (참조 타입)
Class는 참조 타입입니다.
참조 타입은 상수나 변수에 할당하거나 함수에 전달이 될 때 값을 복사하지 않습니다.
인스턴스의 reference (참조), 즉 주소를 이용합니다.
VideoMode라는 class를 정의했습니다.
이전에 structure로 만든 Resolution도 당연히 프로퍼티로 사용할 수 있습니다.
tenEighty라는 인스턴스를 하나 만들었습니다.
그리고 alsoTenEighty라는 상수에 이 인스턴스를 할당했습니다.
이전 값 타입에서는 값이 복사되어 할당되었는데 참조 타입은 다릅니다.
값이 복사되는 게 아니라 할당된 인스턴스의 주소를 저장하게 됩니다.
그럼 alsoTenEighty라는 상수에 접근하면 저장된 주소를 통해 tenEighty에 접근하게 됩니다.
당연히 alsoTenEighty.frameRate에 접근하면 tenEighty.frameRate의 값과 같은 25.0이 나오겠죠??
자 그럼 값 타입과 똑같이 값을 변경해 보겠습니다.
alsoTenEighty.frameRate의 값을 30.0으로 변경했습니다.
그럼 tenEighty.frameRate의 값을 확인해 볼까요??
이럴 수가.. 값 타입과 다르게 tenEighty.frameRate의 값도 변경된 것을 확인할 수 있습니다.
참조 타입은 참조를 이용하기 때문에 원본의 값도 같이 바뀌게 됩니다.
이러한 특성 때문에 class를 사용하면서 값을 변경할 때는 주의해야 합니다.
내가 원치 않는데 다른 곳에서 값이 바뀔 수 있기 때문입니다.
또 하나 눈여겨볼 부분은 tenEighty, alsoTenEighty를 우리는 let으로 선언했습니다.
즉 상수로 선언했는데 alsoTenEighty.frameRate를 변경했습니다.
이게 어떻게 가능할까요??? tenEighty, alsoTenEighty 상수는 둘 다 VideoMode의 인스턴스를 저장하는 게 아닙니다.
VideoMode의 인스턴스를 참조할 뿐입니다. tenEighty,alsoTenEighty 상수에는 결국 주소가 저장되어있을 뿐 인스턴스가 저장돼있는 게 아닙니다.
우리는 주소를 변경한 게 아니라 참조한 인스턴스의 프로퍼티 값을 변경한 것이기 때문에 이게 가능한 겁니다.
VideoMode의 frameRate는 var로 선언되어 있으니 가능합니다.
만약 frameRate가 let이라면 당연히 참조 타입이라도 변경이 불가능합니다.
으음.. 말이 이해하기 어렵게 되었는데 이 부분은 메모리의 Stack과 Heap에 대한 이해가 필요합니다.
자세한 부분은 다음에 추가하도록 하겠습니다.
결론은 참조 타입은 값을 저장한 게 아니라 주소를 저장한 것이고 우리는 주소를 바꾼 게 아니라 참조한 프로퍼티의 값을 변경한 것이기 때문에 tenEighty, alsoTenEighty가 상수여도 프로퍼티의 값을 변경할 수 있는 것입니다.
Identity Operator
Class가 참조 타입이기 때문에 서로 같은 인스턴스를 참조하고 있는지 아닌지 확인할 수 있습니다.
=== (Identical to)
!== (Not identical to)
alsoTenEighty, tenEighty는 서로 같은 인스턴스를 참조하고 있기 때문에 if문이 실행됩니다.
여기서 == (equal)과 헷갈리면 안 됩니다.
=== 은 class 타입인 두 상수나 변수가 서로 같은 인스턴스를 참조하고 있는지 확인하는 operator이고
==은 두 인스턴스가 같은 값을 가지고 있는지 확인하는 operator입니다.
두 말은 서로 다릅니다.
우리가 만든 타입에서 ==을 사용하려면 어떤 값을 비교하여 같다고 표시할지 구현해야 합니다.
VideoType을 예로 들자면 4가지 프로퍼티중에서 어떤 값이 같을 때 equal하다고 할지 정해야합니다.
모두 같을때 equal하다고 할지 frameRate만 같을때 equal하다고 할지 우리가 구현해줘야 합니다.
이에 대해서는 프로토콜을 공부하고 난 뒤에 자세히 공부해보도록 하겠습니다!
참고자료
https://docs.swift.org/swift-book/LanguageGuide/ClassesAndStructures.html
728x90'Programming > Swift' 카테고리의 다른 글
Swift - Computed Property (0) 2021.10.25 Swift - Stored Property (0) 2021.10.24 Swift - Struct & Class (0) 2021.10.20 Swift - Enumeration CaseIterable (0) 2021.10.18 Swift - Enumeration Associated Value (0) 2021.10.16