<1편에서 알아볼 것>
기본적인 초기화 개념
Value type의 initializer delegation
선언
init() {
// 초기화 구문
}
ex)
class Student {
var name: String
init() {
name = "Mini"
print("Student class initialization")
}
}
var student = Student()
student // Student class initialization
name
프로퍼티를 선언하고 초기화 구문 내에서 값을 설정함
struct Student {
var name = "Mini"
}
프로퍼티의 선언과 동시에 값을 할당하여 초기값으로 사용할 수 있음
프로퍼티가 항상 같은 초기값을 같는다면 초기화 구문 내에서 값을 설정하기보다 기본값을 제공하는 것도 고려해볼 수 있다.
class SomeClass {
var someProperty: Int
init(overthreeProperty: Int) {
someProperty = overthreeProperty - 3
}
init(for overFourProperty: Int) {
someProperty = overFourProperty - 4
}
init(_ overFiveProperty: Int) {
someProperty = overFiveProperty - 5
}
}
let someClassA = SomeClass(overthreeProperty: 5)
someClassA.someProperty // 2
let someClassB = SomeClass(for: 5)
someClassB.someProperty // 1
let someClassC = SomeClass(5)
someClassC.someProperty // 0
class SurveyQuestion {
var text: String
var response: String?
init(text: String) {
self.text = text
}
}
let question = SurveyQuestion(text: "Name?")
class SurveyQuestion {
let text: String
var response: String?
init(text: String) {
self.text = text
}
}
let question = SurveyQuestion(text: "Name?")
question
초기화 구문을 만들지 않은 모든 구조체 또는 클래스에 Swift는 기본 초기화 구문을 제공한다.
기본 초기화 구문은 모든 프로퍼티가 기본값으로 설정된 새로운 인스턴스를 생성함.
class Car {
var modelName = "BMW X5"
var ownerName: String?
var purchased = false
}
let car = Car()
modelName
, purchased
ownerName
은 nil로 기본값 설정Car
클래스는 기본 초기화 구문을 제공받음구조체 부분을 잘 공부했다면 떠오를 구조체의 멤버와이즈 초기화 구문!
구조체에서는 모든 프로퍼티에 기본값을 설정해주지 않고, 초기화 구문을 따로 구현해 주지 않아도 멤버와이즈 초기화 구문을 사용하여 인스턴스를 생성할 수 있었다.
모든 프로퍼티가 기본 값을 가지지 않는 경우
struct Size {
var width: Double
var height: Double
}
let twoByTwo = Size(width: 2.0, height: 2.0)
let threeByThree = Size() // error!
// 🚨 Missing arguments for parameters 'width', 'height' in call
let fourByFour = Size(width: 4.0) // error!
// 🚨 Missing argument for parameter 'height' in call
기본 값을 가지지 않는 프로퍼티가 존재하는 경우
struct Size {
var width: Double
var height = 3.0
}
let twoByThree = Size(width: 2.0)
let threeByFour = Size(height: 4.0) // error!
// 🚨 Missing argument for parameter 'width' in call
모든 프로퍼티가 기본 값을 가지는 경우
struct Size {
var width = 2.0
var height = 2.0
}
let twoByTwo = Size() // Size(width: 2.0, height: 2.0)
let threeByThree = Size(width: 3.0, height: 3.0) // Size(width: 3.0, height: 3.0)
let twoByThree = Size(height: 3.0) // Size(width: 2.0, height: 3.0)
초기화 구문은 인스턴스의 초기화 중,
중복된 코드를 방지하기 위해서 다른 초기화 구문을 호출할 수 있음
이 프로세스를 초기화 구문 위임(initializer delegation)이라고 부른다.
오히려 한국어가 더 어려워보여서 이 글에서는 initializer delegation이라 부르겠다.
initializer delegation는 value type, reference type에 따라 동작하는 방식이 다르다.
결론부터 이야기하자면 상속이라는 개념 때문인데, 우선 value type의 경우부터 이야기해 보겠다.
value type은 상속이라는 개념이 존재하지 않으므로 다른 타입이 아닌 자신의 다른 initializer에만 initializer를 위임할 수 있다.
따라서 다른 value type에 initializer를 위임하려면, self.init
을 호출하면 된다.
struct Center {
var x: Int
var y: Int
init(centerX: Int, centerY: Int) {
x = centerX
y = centerY
}
init(center: Int) {
x = center
y = center
}
}
let centerOne = Center(centerX: 10, centerY: 10)
print(centerOne) // Center(x: 10, y: 10)
let centerTwo = Center(center: 3)
print(centerTwo) // Center(x: 3, y: 3)
위의 두 initializer을 잘 보면 두 번째 initializer은 첫 번째와 중복된 코드인 것이 느껴질 것.
initializer delegation은 코드가 중복되는 것을 방지한다고 했었다.
struct Center {
var x: Int
var y: Int
init(centerX: Int, centerY: Int) {
x = centerX
y = centerY
}
init(center: Int) {
self.init(centerX: center, centerY: center)
}
}
let centerThree = Center(center: 7)
print(centerThree) // Center(x: 7, y: 7)
따라서 중복된 코드를 제거하기 위해 init(centerX: Int, centerY: Int)
에 위임할 수 있다.
+)
ref) 예제(https://babbab2.tistory.com/169)
if) initializer를 변수 y는 무조건 0으로 초기화하는 것으로 수정해줘 라고 요청이 들어왔다면!
initializer delegation을 하지 않은 경우
struct Center {
var x: Int
var y: Int
init(centerX: Int, centerY: Int) {
x = centerX
y = 0
}
init(center: Int) {
x = center
y = 0
}
}
initializer delegation을 한 경우
struct Center {
var x: Int
var y: Int
init(centerX: Int, centerY: Int) {
x = centerX
y = 0
}
init(center: Int) {
self.init(centerX: center, centerY: center)
}
}
이런 식으로 유지보수가 훨씬 쉬워진다.
예시는 간단한 코드라서 쉬워진다고 표현하기도 어렵지만, 복잡한 코드에서는 정말 좋을 것 같다. ✨