ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • class 와 struct 그리고 enum
    Swift 2021. 12. 14. 17:30

    안녕하세요!

    오늘은 매일매일 사용하면서도 헷갈리는 친구들이죠??

    class(클래스)struct(구조체)를 알아보도록 할게요!
    추가적으로 enum(열거형)도 같이 비교해보도록 하겠습니다~

     

    우선 가장 많은 분들이 알 거라고 생각되는 class부터 살펴보도록 하겠습니다.

     

    1. class

    가장 큰 특징은 참조타입(call by reference)이라는 거에요.

     

    참조타입이 뭐냐!

     

    그럼 우선 iOS 메모리 구조를 알아야하는디요

     

    대략적으로 이렇게 생겼습니다!

    메모리에 관해서도 공부하고 설명해드리고 싶지만 그것도 양이 엄청나게 많기 때문에 나중에 시간이 나면 다루도록 하겠습니다ㅠㅠ

     

    여기서 저희가 유심히 지켜봐야할 부분은 Stack 영역과 Heap 영역이에요

    우리가 참조 타입 인스턴스를 만들면 Heap 영역에 할당이 되요!

     

     

    그렇다면 저기에 어떻게 Heap 영역에 저장된 실제 정보를 가져오는지 궁금하자나요?

     

    스택 영역에 해당 힙영역을 가르키는 참조(주소)가 저장이 되요

     

     

    이렇게 말이에요! productA가 값 자체를 알고 있는 것이 아니라 참조만 알고 있어요!

     

    productA를 할당받은 productB를 만들면 위의 그림처럼 같은 참조를 가지고 있는 친구만 Stack에 추가되겠죠?

     

    이 상태에서 productA의 price만 변경시켜볼게요

     

     

    A가 참조하고 있던 곳의 값이 변경되었는데 B도 같은 곳을 참조하고 있었으니깐 A와 B의 값이 모두 변경된 것을 확인할 수 있어요

    이게 참조타입이랍니다~!

     

    또 신기한게 하나 있어요!!

    클래스 인스턴스는 참조타입이기 때문에 var가 아닌 let으로 선언해도 내부 프로퍼티를 변경할 수 있어요!!

     

     

    클래스의 또 다른 특징!!

    바로 상속이 가능하다는 거에요!!

     

    상속은 클래스 이름 뒤에 콜론(:)을 붙이고 부모 클래스 이름을 적으면 할 수 있어요

     

    myiPhone의 가격은 따로 할당하지 않았는데도 속성을 가지고 있는것을 볼 수 있어요

     

    하지만 다른 언어와는 다르게 다중 상속은 불가능하답니다...

     

    그리고 깜빡한게 있는데 class는 이니셜라이저가 필요해요!!

    위에 작성된 코드들에서 이니셜라이저가 필요하지 않았던 이유는 프로퍼티에 기본값을 할당해주었기 때문이에요

     

    기본값을 없애주면

     

    이니셜라이저가 없다고 해요!

     

     

    이니셜라이저는 위와 같이 선언한 모든 프로퍼티에 대해서 값을 할당해주면 되요!

    그리고 인스턴스 생성할 때 값을 넣어주면 됩니다!

     

     

    클래스에 대해서는 대략적으로 알아본 것 같으니 다음으로 넘어갈게요!

     

    2. struct

     

    클래스는 참조타입이였으니깐 구조체는 뭘까요?

    감이 오시죠?

     

    구조체는 참조타입이 아닌 값 타입이랍니다!

     

    값타입이 머시냐

     

    와우!

    값 타입은 힙을 전혀 사용하지 않고 스택에만 값이 쌓여요!!

    딱봐도 이리저리 힙 영역을 찾아가야하는 클래스보다 빠를 것 같네요?

     

    만약 여기서 클래스의 경우처럼 productB를 만들면 어떻게 될까요??

     

     

    이렇게 되겠죠 ㅎㅎ

     

     

    그러니깐 A의 가격을 바꾸면 B의 가격은 바뀌지 않는다!

     

     

    또한 값 타입이기 때문에 let으로 선언한 인스턴스는 값을 변경할 수 없어요

     

    또 var로 선언한 인스턴스라도 let 프로퍼티면 변경할 수 없답니다..

     

    오직 var 인스턴스의 var 프로퍼티만 값을 변경할 수 있어요

     

     

    또 아까 제가 상속이 클래스의 특징 중 하나라고 했죠??

     

    그럼 구조체에서는 될까요? 안 될까요?

     

    역시나 안되네요 ㅠㅠ

     

    여기서 잠깐!

     

    혹시 눈치빠른 분들은 눈치채셨을 수도 있는데요~

     

    구조체는 이니셜라이저를 자동으로 만들어줍니다!!

    물론 직접 만들 수도 있지만요 ㅎㅎ

     

     

     

    그럼 이제 마지막 친구를 만나러 가볼까요?

     

     

    3. enum

     

    enum도 값 타입인지 참조타입인지가 중요하겠죠??

     

    enum은 값 타입입니다!!

     

    제가 다른 언어를 잘 모르는데요..

    enum이 존재하는 언어들이 꽤 있는 걸로 알고 있어요

     

    그러나 swift의 enum은 다른 언어와는 차이가 있어요!

     

    Swift의 enum은 연관된 값들을 한 곳에 묶어놓은 타입이에요!!

    타.입

     

    그리고 case들이 그 자체로 값이에요!

     

    이게 무슨 소리냐

     

    case들에 값을 정해주지 않아도 하나하나가 고유의 값이에요

     

    근데 만약 특정 타입으로 지정된 값을 사용하고 싶다면 원시 값이라는게 존재해요

     

    이렇게 열거형 뒤에 지정하고자 하는 타입을 작성하고 각 case에 값을 할당하면 사용할 수 있어요.

    그리고 그 값은 rawValue라는 프로퍼티를 통해 확인할 수 있답니다.

    신기한게 one에만 1값을 할당했는데 자동으로 three에 3이 할당된 것을 볼 수 있어요.

    특이하게 정수타입의 경우 0부터 1씩 증가한 값을 가져요.

    이 경우에는 첫 번째 값을 1로 설정해서 three의 원시값이 3이 된거에요.

     

    enum은 상속이 불가능해요!

     

    여기까지 세 친구의 특징을 알아봤어요

     

    그럼 각각의 친구들을 어느 상황에 쓰냐..

     

    여기서 치트키 한 번 쓰겠습니다..

     

    코드에는 정답은 없다!

     

    그러므로 제가 어느 상황에 쓰는지를 적어볼게요

     

    enum은 다른 두 친구와는 다르니깐 먼저 설명할게요

     

    enum의 경우에는 선택지를 제한하고 싶을 때 많이 사용하는 것 같아요

     

    예를 들어 자동차 객체를 만든다고 해봐요

     

    만들 수 있는 자동차의 색깔이 빨강, 파랑, 검정 뿐인데 초록색 자동차를 만들어달라고 하면 안되자나요

     

    그럴 경우 enum을 사용합니다. 

     

     

    이렇게 입력을 제한해 버리는 거에요!

     

    이럴 경우 아니면 흠..

    enum은 사실 인스턴스를 만들지 않자나요?

     

     

    아래와 같이 프로젝트의 모든 부분에서 사용하고 싶은 함수가 있을 때 enum 안에 static 함수로 만들면 인스턴스를 만들지 않아도 사용할 수 있어요!

    이건 중요한 내용은 아니니깐 넘어갈게요~

     

    그럼 클래스와 구조체는 어떨 경우 사용하는 것이 좋을까요??

     

    실제로 애플이 제공하는 Data 타입들(Int, String)들은 대부분 구조체로 되어있어요!

    이렇게 말이에요

     

    하지만 애플이 제공하는 framework들은 대부분 클래스로 되어있답니다!

    대표적인 예시가 ViewController에요

     

     

    이렇게 애플도 섞어쓰는데 저희가 딱 정하기는 어렵겠죠?

     

    하지만 애플은 구조체 사용을 권장하고 있어요!

     

    최근 나온 SwiftUI만 봐도 알 수 있죠

     

    구조체가 상속도 되지 않고 Stack에 저장되기 때문에 성능이 좋기 때문이 아닐까라고 생각해요!

     

    하지만 분명 상속이 필요한 경우와 참조타입이 필요한 경우도 많기 때문에

     

    판단은 여러분의 몫이라고 생각합니다!!

     

    그럼 이만~


    + 2022.3.10 

    최근 동시성 프로그래밍을 공부하면서 Class와 Struct를 어느 상황에서 사용하는 것이 좋을까 다시 한번 생각해보았습니다.

    애플이 SwiftUI를 비롯해서 Struct 사용을 강조하는 것 또한 단순히 성능 때문만은 아니라고 생각이 됩니다.

     

    멀티 스레드 프로그램에서 mutable한 변수(Swift에서는 var로 선언된)에 접근할 경우 경쟁 상태에 대해서 고려할 필요가 있습니다.

    따라서 immutable한 변수(Swift에서는 let으로 선언된) 변수를 사용하는 것이 용이한 경우가 존재합니다.

     

    Class의 경우 let으로 선언하여도 내부 프로퍼티의 값이 var로 선언되어 있을 경우 값 변경이 가능합니다.

    하지만 Struct의 경우에는 let으로 선언하면 내부 프로퍼티의 값이 var로 선언되어 있어도 값 변경이 불가능합니다.

     

    Struct는 멀티 스레드 환경에서 Side-Effect가 없는 프로그램을 작성하는데 용이합니다.

     

    따라서

     

    1. Immutable해야할 경우

    2. 공유될 필요가 없는 경우

    3. 대입보다는 생성이 많이 되는 타입의 경우

     

    에는 Class보다는 Struct를 사용하는 것이 적합하다고 저는 생각합니다.

    'Swift' 카테고리의 다른 글

    Codable  (0) 2021.12.28
    NSCoder  (0) 2021.12.27
    escaping closure(탈출 클로저)  (0) 2021.12.23
    Hashable  (0) 2021.12.17
    String은 왜 Int로 Subscript 되지 않을까?  (0) 2021.12.15
Designed by Tistory.