[Swift] Structure vs Class

Hyunndy·2023년 3월 7일
0

Swift

목록 보기
2/2

🐸

swift 개념에서 빠질 수 없는 토픽이죠.
구조체냐! 클래스냐!

관련 개념을 이 글에서 한 판 정리 해보도록 하겠습니당.


개요

구조체와 클래스는

  • 데이터를 저장하고(storing data)
  • 행동을 모델링(modeling behavior)
    하는데 쓰입니다.

유사성 때문에 어떤걸 써야할지 개발자들 사이에서도 갈리는데요.
공통점과 차이점을 알아보겠습니다.


공통점

  • 값을 저장하는 프로퍼티(Property) 정의
  • 행동을 제공하는 메서드(Method) 정의
  • 서브스크립트(subscript) 구문을 사용하여 값에 접근 가능
  • 초기화 상태를 위한 initalizer 정의
  • 기본 구현을 넘어 기능적 확장을 위한 extension
  • 특정 종류의 표준 기능을 제공하는 protocol 채택 가능

차이점

초기화 구문(Initializer)

구조체는 멤버 별 초기화 구문이 자동으로 생성된다.
클래스는 멤버 별 초기화를 받지 않는다.

Class Only 특징

  • 상속(Inheritance)
  • 타입 캐스팅을 사용하면 런타임에 클래스 인스턴스의 타입을 확인하고 해석이 가능하다.
  • 초기화 해제 구문(Deinitalizer)를 사용하면 클래스의 인스턴스가 할당된 리소스를 해제할 수 있음
  • 참조 카운팅은 하나 이상의 클래스 인스턴스 참조를 허락함

🐸 구조체는 값 타입(value Type)

Swift에서 구조체(Structure), 열거형(Enum)은 값 타입(value Type) 입니다.
더해서 Int, Float, Double, String, Array, Dictionary, Tuple 같은 Primitive Type은 모두 값 타입이고 구조체로 구현되어 있습니다.

값 타입(Value Type)이란?

👩‍💻 값 타입이란..?
변수, 상수, 함수에 전달될 때 복사되어 전달되는 타입을 말합니다.
구조체가 값 타입이란 것은 구조체의 인스턴스가 값 자체로 취급되고, 참조로 전달되지 않는다는 것을 의미합니다.
값 타입이 복사되서 전달 될 때, 복사된 값은 원본 값과 별개의 독립적인 인스턴스 입니다.

Deep copy(깊은 복사)

Deep Copy는 복사(copy) 연산을 수행할 때 발생하는 개념 중 하나인데요,
객체를 복사할 때, 객체 자체를 복사하여 새로운 객체를 생성하는 개념 입니다.

value Type과 동일하죠?
value Type은 개념적인 느낌이라면.. 이 deep copy는 방법론..? 정도로 생각하면 되겠네요.

최적화

Array, Dictionary, String 같은 표준 라이브러리에 정의된 Collection은 최적화를 사용하여 복사 성능 비용을 줄입니다.
즉시 복사본을 만드는 대신에 이러한 Collection은 원본 인스턴스와 복사본 간에 요소가 저장된 메모리를 공유합니다.
Collection의 복사본 중 하나가 수정되면 그제서야! 수정되기 직전에 복사됩니다.
🐸 코드에서는 항상 즉시 복사되는 것 같지만, 실질적으로는 값이 할당되고 변경되야! 복사본이 보사되는 것입니다.

🐸 클래스는 참조 타입(reference Type)

Swift에서 Class는 참조 타입(reference Type) 입니다.

참조 타입(reference Type)이란?

👩‍💻 참조 타입 이란..?
값이 메모리에 저장된 주소를 참조하는 타입 으로, 인스턴스를 전달할 때 객체 자체를 복사하지 않고 인스턴스가 저장된 메모리 주소를 참조하는 것 입니다.

같은 인스턴스를 여러개의 변수나 상수가 참조할 수 있으며, 하나만 변경해도 같은 참조를 가진 모든 변수, 상수가 변경됩니다.

shallow Copy(얕은 복사)

Shallow copy는 복사(copy) 연산을 수행할 때 발생하는 개념 중 하나인데요,
객체를 복사할 때, 참조하는 메모리 공간의 주소만 복사합니다.
이는 복사된 객체와 원본 객체가 같은 메모리 주소를 공유하게 되어 복사된 객체의 수정이 원본 객체에 영향이 갑니다.

포인터

C, C++에서는 메모리 주소 참조를 위해 포인터를 사용한다는 것을 알것입니다.
Swift에서의 참조는 메모리 주소에 대한 직접적인 포인터가 아니라서 포인터 표시인 * 을 안붙여도 됩니다.
표준 라이브러리는 포인터와 직접 상호작용이 필요한 경우 사용할 수 있는 포인터와 버퍼타입을 제공합니다.


구조체냐, 클래스냐

그래서 뭘 골라야 할까요?

애플에서는 둘 중 어떤걸 사용할지에 대한 대략적인 가이드를 제시합니다.

  • Use structures by default
    (디폴트로 구조체를 사용해라)
  • Use classes when you need Objective-C interoperability.
    (Objectibe-C 와 상호작용이 필요하다면 클래스를 사용해라)
  • Use classes when you need to control the identity of the data you’re modeling.
    (모델링한 데이터의 식별을 제어해야할 때 클래스를 사용해라)
  • Use structures along with protocols to adopt behavior by sharing implementations.
    (구조체는 프로토콜과 함께 사용하여 구현을 공유함으로써 behavior을 채택하는데 사용하세요)

클래스가 참조타입이라는 것을 이용해서 인스턴스를 공유하는데 초점을 맞춰야하거나, 데이터 자체가 식별자가 우선시되서 다르게 간주되는게 중요하다던가... 할 때는 클래스를 쓰지만,
프로토콜과 구조체를 함께써서 확장성있게 구현하라는것 같습니다.


마무리

구조체와 클래스는 정말 단골 질문이죠.
한 판 정리를 했으니 이제 다음것을 보러 가도록 하겠습니다..!

profile
https://hyunndyblog.tistory.com/163 티스토리에서 이사 중

0개의 댓글