개발하는 뚝딱이

[swift] 구조체(struct)와 클래스(class) 비교 본문

swift

[swift] 구조체(struct)와 클래스(class) 비교

개발자뚝딱이 2020. 4. 8. 17:37

책 <스위프트 프로그래밍 3판 ;야곰 지음> 을 정리한 글입니다.

 


구조체와 클래스

struct and Class

 

1. 구조체와 클래스 생성

2. 구조체와 클래스 차이

3. 언제 구조체를 쓸까, 클래스를 쓸까

 

 


 

1. 구조체와 클래스 생성

1. 구조체 정의 / 인스턴스 생성 및 초기화

- 새로운 타입을 지정해주는 것과 마찬가지이므로 구조체 생성 시 대문자 카멜케이스 사용

- 자동으로 생성된 이니셜라이저를 통해 구조체 인스턴스 생성 가능

struct BasicInfo { // 구조체 생성
    var name: String
    var age: Int
}

var myInfo: BasicInfo = BasicInfo(name: "Kim", age: 25) // 인스턴스 생성
myInfo.age = 100

 

2. 클래스의 정의 / 인스턴스 생성 및 초기화 / 인스턴스 소멸

- 새로운 타입을 지정해주는 것과 마찬가지이므로 구조체 생성 시 대문자 카멜케이스 사용

- 저장 프로퍼티 사용이 아니면 이니셜라이저를 생성해야 함

class Person {
    var height: Float = 0.0
    var weight: Float = 0.0
}

var you: Person = Person()
you.height = 180.0
you.weight = 78

- 클래스는 참조값이므로 필요 없을 때 메모리에서 해제됨 = "소멸"

- deinit 메소드가 구현되어 있으면, 소멸 직전 deinit 메서드 호출. deinit 메서드 = 디이니셜라이저 Deinitializer

class Person {
    var height: Float = 0.0
    var weight: Float = 0.0
    
    deinit {
        print("Person 클래스의 인스턴스가 소멸됩니다")
    }
}

var you: Person = Person()
you = nil // 에러, 해제 불가능

var he: Person? = Person()
he = nil // 소멸

 

2. 구조체와 클래스의 차이

1. 공통점

- 프로퍼티, 메서드 정의 가능

- 서브스크립트 문법(subscript)을 통해 클래스가 갖는 값에 접근하도록 서브스크립트 정의 가능

- 이니셜라이저 정의 가능

- 익스텐션으로 새로운 기능 추가 가능

- 특정 프로토콜 준수 가능

 

2. 차이점

  구조체 struct 클래스 class
타입 값 타입 (value type) 참조 타입 (reference type)
상속 여부 X O
타입캐스팅 X O
참조 횟수 계산 Reference Counting X O

 

3. 값 타입과 참조 타입

- 구조체는 값 타입, 클래스는 참조 타입 / '무엇이 전달되느냐'가 구분 포인트!

- 새로운 변수 할당 시, 

  • 값 타입 : 전달될 값이 복사되어 전달됨
  • 참조 타입 : 참조(주소)가 전달됨. C나 C++에서 포인터 개념과 유사

- 값을 복사해왔기 때문에 myInfo와 yourInfo 인스턴스는 별개의 값을 가짐

- 값 타입의 데이터를 함수의 argument로 전달하면, 메모리에 argument를 위한 인스턴스가 새로 생성

- 생성된 argument에는 전달하려는 값이 복사되어 들어감

- 아래 코드블럭은 새로운 변수 할당 시

struct BasicInfo {
    var name: String
    var age: Int
}

var myInfo: BasicInfo = BasicInfo(name: "Kim", age: 25)
var yourInfo: BasicInfo = myInfo // myInfo의 값을 복사하여 할당

print("my name: \(myInfo.name)") // Kim
print("your name: \(yourInfo.name)") // Kim

yourInfo.name = "Lee"

print("my name: \(myInfo.name)") // Kim (값 변동 X)
print("your name: \(yourInfo.name)") // Lee
class Person {
    var height: Float = 0.0
    var weight: Float = 0.0
    
    deinit {
        print("Person 클래스의 인스턴스가 소멸됩니다")
    }
}


var myPerson: Person = Person()
var yourPerson: Person = myPerson // myPerson 참조

print("my weight: \(myPerson.weight)") // 0.0
print("your weight: \(yourPerson.weight)") // 0.0

yourPerson.weight = 100
print("my weight: \(myPerson.weight)") // 100 (값이 바뀜)
print("your weight: \(yourPerson.weight)") // 100 (값이 바뀜)

 

4. 클래스의 식별 연산자 (Identity Operator)

- 두 참조가 같은 인스턴스를 가리키는지 비교

var myPerson: Person = Person()
var yourPerson: Person = myPerson
var anotherPerson: Person = Person()

print(myPerson === yourPerson) // true
print(anotherPerson !== myPerson) // true

 

5. 스위프트의 기본 데이터 타입은, 구조체

- 기본 데이터 타입 (Int, Bool, Array, String 등) 모두 구조체로 구현되어 있음

- 모두 값 타입이므로, 기존의 변수나 상수에는 영향을 끼칠 수가 없음

public struct String {
  public init()
}

 

3. 언제 구조체를 쓸까, 클래스를 쓸까

- 연관된 간단한 값의 집합을 캡슐화하는 것만이 목적일 때

- 캡슐화한 값을 참조하는 것보다 복사하는 것이 합당할 때

- 구조체에 저장된 프로퍼티가 값 타입이며, 참조하는 것보다 복사하는 것이 합당할 때

- 다른 타입으로부터 상속받거나 자신을 상속할 필요가 없을 때

 

위의 4가지 조건 중 하나라도 충족되면 구조체 사용을 권장 (애플의 가이드라인)

 

'swift' 카테고리의 다른 글

[swift] 옵셔널  (0) 2020.04.28
[swift] 메소드 (method)  (0) 2020.04.27
[swift] 프로퍼티(property)  (0) 2020.04.15
[swift] 연산자  (0) 2020.04.06
[swift] 데이터 타입  (0) 2020.04.02