Swift

[Swift] 구조체와 클래스

yevdev 2022. 3. 17. 16:02
구조체의 인스턴스는 타입 (전달될 값이 복사되어 전달)
클래스의 인스턴스는 참조 타입 (값을 복사하지 않고 참조(주소)가 전달)

 

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 스위프트 프로그래밍 - 야곰