주요 이니셜라이저
필요에 따라 부모클래스의 이니셜라이저를 호출할 수 있습니다.
이니셜라이저가 정의된 클래스의 모든 프로퍼티를 초기화해야 함
조상클래스의 지정 이니셜라이저가 자손클래스의 지정 이니셜라이저 역할을 한다면 자손클래스의 지정 이니셜라이저가 없을 수도 있음
→ 하지만 그렇기 위해서는 자손 클래스는 옵셔널 저장 프로퍼티 외의 저장 프로퍼티는 가질 수 없을 것
init(매개변수) {
초기화 구문
}
편의 이니셜라이저는 초기화를 좀 더 손쉽게 도와주는 역할
편의 이니셜라이저는 지정 이니셜라이저를 자신 내부에서 호출 함
클래스 설계자의 의도대로 외부에서 사용하길 원하거나 인스턴스 생성 코드를 작성하는 수고를 덜 때 유용하게 사용
convenience init(매개변수) {
초기화 구문
}
지정 이니셜라이저와 편의 이니셜라이저 사이의 관계에서 3가지 규칙이 있습니다.
스위프트의 클래스 초기화는 2단계를 거칩니다.
클래스의 인스턴스는 초기화 1단계를 마치기 전까지는 아직 유효하지 않습니다. 클래스의 인스턴스가 초기화 1단계를 마쳤을 때 비로소 유효한 인스턴스가 되는 것입니다.
위 네 가지 안전확인에 근거하여 어떻게 2단계 초기화가 이루어지는지 살펴보겠습니다.
class Person {
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
class Student: Person {
var major: String
init(name: String, age: Int, major: String) {
self.major = major
super.init(name: name, age: age)
}
convenience init(major: String) {
self.init(name: "피터", age: 30, major: major)
}
}
기본적으로는 스위프트의 이니셜라이저는 부모클래스의 이니셜라이저를 상속받지 않습니다. 부모클래스의 이니셜라이저는 자식클래스에 최적화되어 있지 않아서, 부모클래스의 이니셜라이저를 사용했을 때 자식클래스의 새로운 인스턴스가 완전하고 정확하게 초기화되지 않는 상황을 방지하고자 합니다.
단, 예외적으로 특정한 상황에서는 부모클래스의 이니셜라이저가 상속되기도 합니다. (이니셜라이저 자동 상속)
부모클래스의 이니셜라이저 사용하기
기본적으로 스위프트의 이니셜라이저는 부모클래스의 이니셜라이저를 상속받지 않지만 특정 조건에 부합한다면 부모클래스의 이니셜라이저가 자동으로 상속됩니다.
🔔 특정 조건이란?
자식클래스에서 프로퍼티 기본값을 모두 제공한다고 가정할 때,
규칙 1. 자식클래스에서 별도의 지정 이니셜라이저를 구현하지 않는다면, 부모클래스의 지정 이니셜라이저가 자동으로 상속됩니다.
규칙 2. 만약 규칙 1.에 따라 저식클래스에서 부모클래스의 지정 이니셜라이저를 자동으로 상속받은 경우 또는 부모클래스의 지정 이니셜라이저를 모두 재정의하여 부모클래스와 동일한 지정 이니셜라이저를 모두 사용할 수 있는 상황이라면 부모클래스의 편의 이니셜라이저가 모두 자동으로 상속됩니다.
자동 상속 규칙은 자식클래스의 편의 이니셜라이저를 추가한다고 하더라도 유효합니다.
또, 부모클래스의 지정 이니셜라이저를 자식클래스의 이니셜라이저르 구현하더라도 규칙 2.를 충족합니다.
class Person {
var name: String
init(name: String) {
self.name = name
}
convenience init() {
self.init(name: "알 수 없음")
}
}
class Student: Person {
var major: String
// major의 기본값이 없지만 이니셜라이저에서 적절히 초기화
init(name: String, major: String) {
self.major = major
super.init(name: name)
}
// 부모클래스의 지정 이니셜라이저를 모두 재정의
// -> 부모클래스와 지정 이니셜라이저와 동일한 이니셜라이저를 모두 사용 가능
// -> 규칙1에 의하여 부모클래스의 편의 이니셜라이저가 자동으로 상속됨
override init(name: String) {
self.major = "알 수 없음"
super.init(name: name)
}
}
let person: Person = Person.init()
// Student에는 없는 이니셜라이저, 부모클래스의 편의 이니셜라이저 자동 상속(규칙 2)
let student: Student = Student.init()
print(person.name)
print(student.name)
// 결과
알 수 없음
알 수 없음
위의 코드에서 Student에 편의 이니셜라이저를 추가하면 ?
import Foundation
class Person {
var name: String
init(name: String) {
self.name = name
}
convenience init() {
self.init(name: "알 수 없음")
}
}
class Student: Person {
var major: String
init(name: String, major: String) {
self.major = major
super.init(name: name)
}
override init(name: String) {
self.major = "알 수 없음"
super.init(name: name)
}
convenience init(major: String) {
self.init()
self.major = major
}
}
let person: Person = Person.init()
let student: Student = Student.init(major: "이러쿵 저러쿵")
print(person.name)
print(person.name)
print(student.name)
규칙 2에 따라서 편의 이니셜라이저는 자동 상속에는 아무런 영향을 미치지 않았습니다.
required 수식어를 클래스의 이니셜라이저 앞에 명시해주면 이 클래스를 상속받은 자식클래스에서 반드시 해당 이니셜라이저를 구현해주어야 합니다.
required init() {
}
만약 상속받은 클래스에서 별도의 지정 이니셜라이저가 없다면 요구 이니셜라이저는 자동 상속되지만 그렇지 않은 경우에는 요구 이니셜라이저를 재정의 해주어야 합니다.
required override init() {
}
자료 출처: 야곰 스위프트 프로그래밍 3판
"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."