`class`와 `struct`는 언뜻 보면 비슷해 보일 수 있다.
class Vehicle {
var wheel = 4
func move() {
print("move forward")
}
}
struct Vehicle {
var wheel = 4
func move() {
print("move forward")
}
}
다음 예시를 보면 `class`와 `struct`라는 이름만 달라졌지 그 이외에 달라진 것은 없어보인다.
let vehicle1 = Vehicle()
또한 사용을 할 때도 위와 같이 같은 꼴이다 보니 두 가지를 굳이 왜 구분해놓았지?라고 생각할 수 있다.
왜냐? 내가 처음에 그랬으니까~
하지만 두개는 엄연히 다른 것이다.! 하나하나 어디가 다른지 같이 짚어보자.
1. 상속
`class`와 `struct`는 상속 가능 여부에 차이가 있다.
결론적으로 말하면 `struct`는 상속이 불가능하다!
`class`는 아래와 같은 방식으로 상속을 할 수 있다.
class Car: Vehicle{
}
상속을 하게 되면 부모클래스인 `Vehicle`내의 프로퍼티나 함수들을 자녀클래스인 `Car`에서 사용할 수 있다.
let car = Car()
car.move()
// 출력 : move forward
2. 초기화 (생성자)
`class`는 내부의 프로퍼티가 초기화되지 않은 상태라면 꼭 생성자를 써주어야한다.
`struct`는 생성자가 필요하지 않기 때문에 아래코드처럼 프로퍼티가 초기화되지 않은 상태로 존재해도 따로 오류가 나지 않는다.
struct Vehicle {
var wheel: Int
func move() {
print("move forward")
}
}
하지만 `class`에서는 `init`이라는 생성자를 써 주지 않으면 오류가 난다.
class Vehicle {
var wheel: Int
init(wheel: Int){
self.wheel = wheel
}
func move() {
print("move forward")
}
}
하지만 또 두 개가 비슷해 보이는 것은 사용방법 때문인데, `class`와 `struct` 둘 다 아래와 같이 사용해야한다.
let vehicle1 = Vehicle(wheel: 4)
`struct`는 생성자는 만들 필요가 없지만, 값이 없는 프로퍼티가 있어서는 안된다. 결국 같은 방식으로 사용해한다.
3. 참조
`class` 코드에 새로운 함수를 추가해보자.
class Vehicle {
var wheel: Int
init(wheel: Int) {
self.wheel = wheel
}
func move() {
print("move forward")
}
func changeWheelNumber(amount: Int) {
wheel = wheel - amount
}
}
let vehicle1 = Vehicle(wheel: 10)
let vehicle2 = vehicle1
바퀴 수를 `10`이라고 두고, `vehicle2`라는 객체를 `vehicle1`과 같다고 만들어주었다.
이 상태로 `changeWheelNumber`이라는 함수를 사용하면 `vehicle2`의 `wheel` 수는 어떻게 될까?
vehicle1.changeWheelNumber(amount: 3)
print(vehicle1.wheel)
print(vehicle2.wheel)
// 출력 : 7
// 출력 : 7
우리는 `vehicle2`의 `wheel`을 변경한 것이 아닌데도 불구하고 `vehicle2`의 `wheel` 값이 변했다는 것을 알 수 있다.
이것은 `vehicle2`가 `vehicle1`을 "참조"하고 있기 때문이고 `let vehicle2 = vehicle1`만으로는 새로운 객체를 생성한 것이 아닌 것을 알 수 있다.
`vehicle2`를 새로운 객체로 만들어주기 위해서는 `let vehicle2 = Vehicle(wheel: 10)`으로 생성자부터 써주어야한다.
이것을 `struct`로 써보자.
struct Vehicle {
var wheel: Int
func move() {
print("move forward")
}
mutating func changeWheelNumber(amount: Int) {
wheel = wheel - amount
}
}
`struct`에서는 내부 프로퍼티의 값을 수정해야할 때, `mutating` 키워드를 꼭 써주어야한다.
구조체는 값 타입인데 이것은 프로퍼티를 메서드 내에서 수정할 수 없다.
따라서`mutating`을 붙여줘서 구조체 전체를 새로 초기화시킴으로써 수정한다.
var vehicle1 = Vehicle(wheel: 10)
var vehicle2 = vehicle1
vehicle1.changeWheelNumber(amount: 3)
print(vehicle1.wheel)
print(vehicle2.wheel)
// 출력 : 7
// 출력 : 10
같은 코드를 써주었을 때, `vehicle1`을 상수로 설정해줄 수가 없는데,
`mutating` 때문에 `struct` 전체가 변화하는 것이기 때문에 `var`로 써야한다.
출력을 보게 되면 `vehicle2`의 값은 변하지 않은 것을 알 수 있다. 이것을 통해서 구조체는 참조가 아닌 "복사"를 해서 새로운 객체를 만들어 준다는 것을 알 수 있다.
'iOS > Swift' 카테고리의 다른 글
[Swift] while문의 구문이름표를 알아보자 (0) | 2023.08.04 |
---|---|
[Swift] String 관련 메서드 정리 (2) | 2023.08.03 |
[Swift] 튜플 (Tuple) 알아보기 (0) | 2023.08.02 |
[Swift] Map 알아보기 (1) | 2023.08.01 |