목차
1. 클래스 vs 구조체 - 공통점과 차이점
2. class와 struct에서 생성자/소멸자를 호출해보자
3. 값 타입(Value Type) vs 참조 타입(Reference Type)
4. 구조체 선택 기준
1️⃣ 속성(Property) 정의 가능
: 클래스와 구조체 모두 변수나 상수와 같은 속성(Property)를 정의할 수 있다.
2️⃣ 메소드(Method) 정의 가능
: strutct 구조체도 클래스와 동일하게 함수(Method)를 정의할 수 있다.
3️⃣ 생성자를 통한 초기 설정 가능
: struct 구조체도 생성자를 통해 인스턴스 초기 설정이 가능하다.
4️⃣ extension과 protocol을 사용 가능
⚠️ 클래스는 가능하지만 구조체는 가능하지 않는 것들이다.
1️⃣ 상속(Inheritance)
: 클래스는 한 클래스가 가지고 있는 특징을 다른 클래스가 그대로 재사용할 수 있다. (구조체 X)
2️⃣ 타입 캐스팅(Type Casting)
: 클래스는 타입을 바꿀 수 있다. (구조체 X)
3️⃣ 소멸자를 통한 리소스 정리
: 클래스는 생성자의 반대 개념인 소멸자를 통해 인스턴스 생성을 통해 발생된 리소스를 정리할 수 있다. (구조체 X)
4️⃣ 참조 타입(Reference Type)
: 클래스는 참조 타입이다.
(부연 설명) 구조체는 변수나 상수에 할당이 되거나 함수 인자로 넘길 때 구조체의 데이터가 복사가 되는 value 타입이다. 하지만 클래스는 데이터가 복사가 되는 것이 아니라 참조 횟수만 증가하는 reference type이다.
✅ 클래스의 생성자/소멸자 호출 결과
if문 실행 결과 생성자와 소멸자가 둘다 호출이 되는 것을 알 수 있다.
⬇️ 실행 결과
circle이라는 인스턴스는 if라는 scope 안에서만 유효하기 때문에 if문이 종료되면 circle의 인스턴스는 소멸되어 소멸자가 호출된다.
✅ 구조체의 생성자/소멸자 호출 결과
위의 class 키워드를 struct로 바꾸고 실행해보면 아래와 같이 소멸자는 클래스에서만 사용 가능하다는 에러가 발생한다.
즉, 소멸자를 통한 리소스 정리는 클래스에서만 가능하다.
⬇️ 실행 결과
‼️error: deinitializers may only be declared within a class or actor
✅ 구조체를 복사한 결과
✅ 클래스를 복사한 결과
✅ 구조체와 클래스 비교 설명
var square2 = square1
struct 라면 square1의 데이터(값)를 square2에 복사해주고, class라면 square1이 가리키고 있는 메모리 주소를 square2에 복사해준다. 즉, struct는 서로 다른 독립된 메모리를 공간을 갖고 있는 인스턴스 square1과 sqaure2, 2개가 생성이 된다. class는 Square 클래스의 메모리를 가리키는 주소를 sqaure2에게 나누어 줌으로써 레퍼런스 참조 개수가 1개에서 2개로 바뀌게 되는 것이다. 따라서 클래스라면 square1과 square2는 같은 메모리를 공유하게 되어 length가 둘다 10이 된다.
✅ swift의 자료형
Int, String, Array 같은 대부분의 swift 자료형은 struct 구조체로 만들어져있다.
그 말인 즉슨 다른 변수나 상수에 할당을 하거나 함수 인자로 넘길 때 레퍼런스가 아닌 값(value) 복사가 일어난다. 기억해야할 점은 struct는 값 타입이고 class는 참조 타입이다.
🤔 여기서 드는 생각은.. 그렇다면 구조체는 언제 선택해야 할까?
1) 캡슐화할 대상이 간단하고 적을 때
몇 가지 간단한 데이터 값을 캡슐화하는 것이 주요 목적일 때 구조체를 사용한다.
2) 값 복사
할당 및 전달 시 레퍼런스 복사가 아닌 값(value) 복사가 합리적일 때, 구조체를 사용하도록 한다.
3) 캡슐화하는 모든 속성이 값 타입
캡슐화할 대상의 모든 속성이 값 타입이어서 값 복사가 일어나는게 맞을 때, 구조체를 사용하도록 한다.
4) 상속(Inheritance)이 필요 없을 때
클래스와 달리 구조체는 상속이 불가능하므로 상속 없이 사용하고 싶을 때, 구조체를 사용하도록 한다.
하지만...
‼️공식문서에도 있지만 반드시 구조체를 사용해야 하는 케이스는 많지 않기 때문에 대부분의 경우는 클래스를 만들어 인스턴스를 생성해서 사용하면 된다.