[Programming Language]/[Swift]

[Swift] 구조체(Structure) vs 클래스(Class) 차이점

Semincolon 2024. 11. 4. 09:14

1. 구조체(Structure)와 클래스(Class)의 공통점

구조체클래스는 비슷하면서도 다르다. 둘다 아래와 같은 기능을 공통적으로 할 수 있다.

  • Property(프로퍼티) 정의
  • Method(메서드) 정의
  • Subscript(서브스크립트) 정의
  • init(초기화 함수) 정의
  • extension(확장)
  • Protocol(프로토콜) 준수

 

2. 구조체(Structure)와 클래스(Class)의 차이점

2-1. 기본 초기화 함수

구조체와 클래스 모두 프로퍼티의 기본값을 정의할 수 있다.

struct PersonStructure {
    var name: String = ""
    var age: Int = 0
}

class PersonClass {
    var name: String = ""
    var age: Int = 0
}

 

그러나 프로퍼티의 기본값을 정의하지 않는다면 구조체프로퍼티의 기본값을 매개변수로 하는 기본 초기화 함수를 제공하기 때문에 오류가 발생하지 않지만, 클래스기본 초기화 함수가 매개변수를 갖지 않기 때문에 오류가 발생한다.

class PersonClass { // Class 'PersonClass' has no initializers
    var name: String
    var age: Int
}

구조체는 프로퍼티의 기본값을 매개변수로 갖는 초기화 함수를 제공

 

따라서 클래스에서는 프로퍼티의 기본값을 정의하거나, 값이 없을 수 있음을 나타내기 위해 옵셔널 타입을 사용하거나, 직접 초기화 함수를 선언해주어야 한다.

기본값 정의 옵셔널 타입 사용 직접 초기화 함수 선언

 

2-2. 상속

구조체상속이 불가능하지만 클래스상속이 가능하다.

구조체에서는 이러한 표현이 Vehicle이라는 프로토콜을 준수한다는 것으로 해석된다
클래스는 상속 가능하다

 

2-3. 구조체는 값 타입(Value Types), 클래스는 참조 타입(Reference Type)

구조체는 그 자체로 값이 되는 값 타입이지만, 클래스는 값에 대한 참조를 나타내는 참조 타입이다.

 

2-3-1. 구조체는 깊은 복사(deep copy), 클래스는 얕은 복사(shallow copy)

값 타입인 구조체는 값을 복사할 때 깊은 복사가 이뤄진다. 이는 복사한 값과 기존 값이 서로 다른 값임을 뜻한다.

struct Person {
    var name: String
}

var p1 = Person(name: "John")

var p2 = p1 // 깊은 복사(deep copy)
p2.name = "Dean"

print(p1) // Person(name: "John")
print(p2) // Person(name: "Dean")

 

반면 참조 타입인 클래스는 값을 복사할 때 얕은 복사가 이뤄진다. 클래스는 값의 메모리 주소를 저장하는 참조 타입이므로 구조체와는 다르게 복사한 값과 기존 값이 궁극적으로는 서로 같은 값을 뜻하게 된다.

class Person {
    var name: String = ""
    
    init(name: String) {
        self.name = name
    }
}

var p1 = Person(name: "John")

var p2 = p1 // 얕은 복사(deep copy)
p2.name = "Dean"

print(p1.name) // Dean
print(p2.name) // Dean

 

2-3-2. let 키워드를 사용했을 때 구조체는 값의 변경이 불가, 클래스는 가능

구조체그 자체로 값을 나타내기let 키워드로 선언되어 한번 값이 정해지고 나면 수정될 수 없다.

struct Person {
    var name: String = ""
}

let p1 = Person(name: "John")
p1.name = "Dean" // Cannot assign to property: 'p1' is a 'let' constant

 

클래스값에 대한 참조(주소값)을 나타내기에 주소값은 변경이 불가하나 값 자체는 변경할 수 있다.

class Person {
    var name: String = ""
    
    init(name: String) {
        self.name = name
    }
}

let p1 = Person(name: "John")
p1.name = "Dean" // let 키워드로 선언되었지만 참조하는 값에 대한 변경은 가능
print(p1.name) // Dean

let p2 = Person(name: "Sally")

// ❗️주소값 자체는 변경할 수 업음❗️
p1 = p2 // Cannot assign to value: 'p1' is a 'let' constant

 

2-4. === 비교 연산자

클래스=== 연산자(등호 3개)를 사용하여 같은 참조를 하고 있는지에 대해 확인할 수 있다.

class Rectangle {
    var width: Int
    var height: Int
    
    init(width: Int, height: Int) {
        self.width = width
        self.height = height
    }
}

let r1 = Rectangle(width: 10, height: 20)
let r2 = r1
let r3 = Rectangle(width: 20, height: 20)

print(r1 === r2) // true
print(r1 === r3) // false

 

!== 연산자=== 연산자의 결과와 반대되는 값을 뜻한다.

 


지금까지 공부한 내용을 기준으로 구조체와 클래스의 차이점을 정리해보았다.

앞으로 공부하면서 차이점을 추가로 발견하게 된다면 관련 내용을 추가해야겠다.

 

끝!