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. 상속
구조체는 상속이 불가능하지만 클래스는 상속이 가능하다.
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
!== 연산자는 === 연산자의 결과와 반대되는 값을 뜻한다.
지금까지 공부한 내용을 기준으로 구조체와 클래스의 차이점을 정리해보았다.
앞으로 공부하면서 차이점을 추가로 발견하게 된다면 관련 내용을 추가해야겠다.
끝!
'[Programming Language] > [Swift]' 카테고리의 다른 글
[Swift] 프로퍼티 관찰자(Property Observers) (0) | 2024.11.06 |
---|---|
[Swift] 프로퍼티(Property) [Stored •Computed, getter, setter, read-only] (8) | 2024.11.05 |
[Swift] ~= 연산자 : 범위 확인 연산자, 패턴 매치 연산자 (0) | 2024.10.24 |
[Swift] String.allSatisfy(_:) 함수란? (0) | 2024.09.23 |
[Swift] SubSequence(ArraySlice)를 그냥 사용하는 것과 저장하고 사용하는 것의 속도 차이가 발생하는 이유는? (1) | 2024.09.22 |