Swift는 구조체를 사용한다. 기본적으로 구조체도 클래스처럼 객체 지향 프로그래밍의 기초를 따르며 데이터와 기능을 재사용할 수 있는 객체로 캡슐화하는 방법을 제공한다.
구조체의 선언 방법
구조체도 클래스와 선언 방법이 비슷하다. 단지 class 대신 struct 키워드를 사용하는게 다르다.
struct Address {
private var cityName : String = ""
var city : String {
get {
cityName
}
set {
cityName = newValue.uppercased()
}
}
}
클래스와 마찬가지로 구조체도 확장될 수 있으며, 프로토콜을 채택하거나 초기화를 가질 수 있다. 그렇다면 구조체는 클래스와 무엇이 다를까?
값 타입 vs 참조 타입
클래스와 구조체는 겉으로 보기엔 매우 비슷해보이지만, 아주 큰 차이가 있다.
- 구조체는 값 타입이고, 클래스는 참조 타입이다
- 값 타입이기 때문에, 새로운 변수에 기존 구조체를 할당하거나, 함수에 매개변수로 넘길 때의 동작 방식이 클래스와는 다르다
- 구조체 인스턴스가 복사되거나 메소드에 전달될 때 인스턴스의 복사본이 전달된다.
- 클래스를 담는 변수는 해당 클래스 인스턴스 주소에 대한 값을 가지고, 함수로 넘기거나 복사될 때 인스턴스의 주소값이 넘어가기 때문에 같은 인스턴스를 가리킨다.
위와 같은 차이 때문에 struct 는 매번 새로운 인스턴스를 가지게 되고, 클래스는 함수로 넘기거나 다른 참조 변수에 할당할 때 같은 인스턴스를 가리킨다.
더 쉬운 이해를 위해 예제를 보도록 하자. Test 프로토콜을 따르는 클래스와 구조체를 만들어 주었다.
protocol Test {
var name : String {get set}
}
struct Struct : Test {
var name : String
init(name:String){
self.name = name
}
}
class Class : Test {
var name : String
init(name:String){
self.name = name
}
}
이제 이 프로토콜을 따르는 타입을 매개변수로 받아, name 프로퍼티를 변경하는 함수를 생성했다.
func test( a : Test){
var sample = a
sample.name = "HoHO"
}
그 다음 클래스와 구조체의 인스턴스를 만들어서 위 함수에 넘긴 뒤, name 프로퍼티를 출력해 보았다.
var A = Class(name:"AA")
var B = Struct(name:"BB")
test(a: A)
test(a: B)
print(A.name)
print(B.name)
//출력 결과
HoHO
BB
A의 경우 인스턴스의 주소값이 함수로 넘어갔기 때문에, 함수 내 변경사항이 원본 인스턴스에 그대로 반영되는 것을 확인 가능하다.
그러나 구조체의 경우 완전히 새로운 인스턴스가 함수로 넘어가기 때문에, 함수 내 변경사항이 원본 인스턴스에 적용되지 않는다.
위 함수에서 상수로 넘어온 데이터의 섀도 복사본을 생성해주기 때문에, 사실상 구조체의 인스턴스가 2개나 더 생기게 된다.
구조체와 클래스는 언제 사용할까?
구조체는 완전히 새로운 인스턴스가 생성되기 때문에, 멀티 스레드 환경에서 동기화 문제를 신경쓰지 않아도 된다. 그러나 상속이 필요하거나 데이터가 캡슐화된 하나의 인스턴스만 필요한 경우에는 클래스를 사용해야 한다. 또는 인스턴스가 소멸될 때 리소스를 확보하기 위한 작업이 필요할 때도 클래스를 사용해야 한다.
'Swift' 카테고리의 다른 글
Swift 에러 핸들링 (0) | 2022.02.11 |
---|---|
Swift 딕셔너리 (0) | 2022.02.10 |
Swift 프로퍼티 래퍼 (0) | 2022.02.10 |
Swift 함수 - 2 (0) | 2022.02.09 |
Swift 5 - 함수 1 (0) | 2022.02.09 |
Comment