구조체의 인스턴스는 값 타입 (전달될 값이 복사되어 전달)
클래스의 인스턴스는 참조 타입 (값을 복사하지 않고 참조(주소)가 전달)
1️⃣ 구조체
// 구조체 정의
struct BasicInformation {
var name: String
var age: Int
}
// 구조체 인스턴스의 생성 및 초기화
// 프로퍼티 이름(name, age)으로 자동 생성된 이니셜라이즈를 사용하여 구조체를 생성
var yejinInfo: BasicInformation = BasicInformation(name: "yejin", age: 23)
yejinInfo.name = "hyejin" // 변경 가능
yejinInfo.age = 25 // 변경 가능
// 프로퍼티가 상수 let 의 타입일 경우 변경 불가
➰스위프트의 기본 데이터 타입은 모두 구조체이다.
2️⃣ 클래스
- 스위프트의 클래스는 부모 클래스가 없더라도 상속 없이 단독으로 정의가 가능
- 상속받은 클래스를 정의할 경우에는 클래스 이름 뒤에 콜론(:)을 써주고 부모클래스 이름을 명시한다.
// 클래스 정의
class Person{
var height: Float = 0.0
var weight: Float = 0.0
}
// 클래스의 인스턴스 생성 및 사용
// Person클래스에서는 프로퍼티의 기본값이 지정되어 있으므로 전달인자를 통하여 따로 초깃값을 전달해주지 않아도 된다.
var yejin: Person = Person()
yejin.height = 123.4
yejin.weight = 12.4
➰클래스 인스턴스의 소멸
클래스 인스턴스는 참조 타입이므로 더는 참조가 필요 없을 때 메모리에서 해제된다 = 소멸
소멸되기 직전에 deinit라는 메서드가 호출된다.
deinit 메서드 = 디이니셜라이저
- 클래스당 하나만 구현할 수 있으며, 매개변수와 반환 값을 가질 수 있다.
- 매개변수를 위한 소괄호도 적어주지 않는다.
class Person{
var height: Float = 0.0
var weight: Float = 0.0
deinit{
print("Person 클래스와 인스턴스가 소멸됩니다.")
}
}
var yejin: Person? = Person()
yejin = nil // Person 클래스의 인스턴스가 소멸됩니다.
3️⃣ 구조체와 클래스의 차이
struct BasicInformation {
let name: String
var age: Int
}
var yejinInfo: BasicInformation = BasicInformation(name: "yejin", age: 23)
yejinInfo.age = 24
// yejinInfo의 값을 복사하여 할당한다!
var friendInfo: BasicInformation = yejinInfo
print("yejin's age: \(yejinInfo.age)") // 24
print("friend's age: \(friendInfo.age)") // 24
friendInfo.age = 25
print("yejin's age: \(yejinInfo.age)") // 24
print("friend's age: \(friendInfo.age)") // 25
class Person {
var height: Float = 0.0
var weight: Float = 0.0
}
var yejin: Person = Person()
var friend: Person = yejin
print("yejin's height: \(yejin.height)") // 0.0
print("friend's height: \(friend.height)") // 0.0
friend.height = 154.4
print("yejin's height: \(yejin.height)") // 154.4
print("friend's height: \(friend.height)") // 154.4
// friend는 yejin을 참고하기 때문에 값이 변동된다.
// friend.height을 통해, yejin이 참조하는 곳과 friend가 참고하는 곳이 같음을 알 수 있다.
print("0--------")
func changeBasicInfo(_ info: BasicInformation) {
var copiedInfo: BasicInformation = info
copiedInfo.age = 1
}
func changePersonInfo(_ info: Person){
info.height = 155.2
}
// changeBasicInfo(_ :)로 전달되는 전달인자는 값이 복사되어 전달되기 때문에
// yejinInfo의 값만 전달되는 것이다.
changeBasicInfo(yejinInfo)
print("yejin's age: \(yejinInfo.age)") // 24
// changePersonInfo(_ :)의 전달인자로 yejin의 참조가 전달되기 때문에
// yejin이 참조하는 값들에 변화가 생긴다.
changePersonInfo(yejin)
print("yejin's height: \(yejin.height)") // 155.2
➰식별연산자의 사용 : 클래스의 인스턴스끼리 참조가 같은지 확인할 때 사용
var yejin: Person = Person()
let friend: Person = yejin // yejin의 참조를 할당
let anotherFriend: Person = Person() // 새로운 인스턴스를 생성
print(yejin === frined) // true
print(yejin === anotherFriend) // false
print(friend !== anotherFriend) // true
4️⃣ 구조체와 클래스 선택해서 사용하기
애플은 아래의 조건 중 하나 이상에 해당한다면 구조체를 사용하는 것을 권장하고 있다.
1. 연관된 간단한 값의 집합을 캡슐화하는 것만이 목적일 때
2. 캡슐화한 값을 참조하는 것보다 복사하는 것이 합당할 때
3. 구조체에 저장된 프로퍼티가 값 타입이며 참조하는 것보다 복사하는 것이 합당할 때
4. 다른 타입으로부터 상속받거나 자신을 상속할 필요가 없을 땐
➰ 구조체를 사용하기에 가장 적합한 예 : 좌표계
Reference
Swift 스위프트 프로그래밍 - 야곰
'Swift' 카테고리의 다른 글
[Swift] self 프로퍼티 (feat. mutating, 타입메서드) (0) | 2022.03.19 |
---|---|
[Swift] 연산 프로퍼티로 가독성 높이기! (0) | 2022.03.19 |
[Swift] 옵셔널 : 옵셔널 추출 (0) | 2022.03.17 |
[Swift] 함수 : 입출력 매개변수 활용, 데이터 타입으로써의 함수, 중첩 함수, @discardableResult (0) | 2022.03.16 |
[Swift] 사용자 정의 연산자 : 전위, 중위, 후위 연산자 (0) | 2022.03.15 |