Swift Initialization
2018, Oct 07
* Initialize(초기화), Deinitialize
- 일반적으로 OOP에서는 생성자(Constructor)와 파괴자(Destructor) 라는 개념이 존재. 객체의 탄생과 사라지는 시점에 맞춰 시작과 끝에 호출되는 메소드.
- 스위프트에서는 초기화(Initialization)와 마무리(Deinitialization)라는 개념의 용어를 사용.
-
Initialization
생성자(Constructor) 개념은 클래스가 객체화 될 때 자동으로 실행되는 메소드(init)를 지칭. init은 구조체(struct)와 클래스(class) 모두 지원
- self : 메모리에 올라간 함수? 클래스? 를 다시 호출할 때 쓰는 용어
- lazy : lazy의 변수가 처음 호출될 때 초기화값이 할당됨
- init() 은 일반 메소드 선언과 다르게 func 키워드가 필요 없다.
또한, override 시 override를 표기할 필요가 없다.
-
init 저장 속성 값 (Setting Intial Values for Stored Properities)
class SimpleClass {
var value: Int
init() {
value = 0
}
}
let simple = SimpleClass()
/* init 저장 속성 값을 이렇게 설정해 줘도 되지만 보통 저장 속성 값을 쓰는 경우는 class를 인스턴스화 시킬 때 초기값을 바로 설정해줄 때 사용한다. 그러기 위해선 init에 argument를 설정해주면 된다.
*/
- init은 클래스나 구조체의 인스턴스를 생성 할 때 넘기는 매개변수 구조에 따라 호출 되는 것이 다르다.
class SimpleClass2 {
/*
let value: Int
변수 선언할 때 let으로 하면 인스턴스화 할 때
초기화 과정에서만 변경 가능하고,
초기화 설정이 끝난 뒤에는 변경 불가능하다.
*/
var value: Int
/*
init(v: Int) {
self.value = 5
}
이렇게 값을 바로 넣어주게 되면 인스턴스화 할 때
let simple = SimpleClass2(v: 55) 값을 넣어줘도
값은 변하지 않는다.
simple.value == 5
*/
// 인스턴스화할 때 인자를 받아 값을 초기화 설정
init(v: Int) { // 앞에서 (var value: Int)로
self.value = v // 이미 value의 타입을 정해주었지만
} // init(v) -> error,
// init(v: Int)같은 타입 입력해야 함
init() {
self.value = -999
}
}
두 개의 init 이 override 되어 있다. 하지만 매개변수가 다르다. 특히 하나는 매개변수가 존재하지 않는다.
-
init() : 기본 초기화 메소드(Default Initialization)로 아래와 같이 그냥 인스턴스를 생성하면 호출된다.
let simple1 = SimpleClass2()
print(simple1.value)
// -999
-
init( v: Int) : 인자를 넣어서 초기화 메소드를 이용할 때
let simple2 = SimpleClass2(v: 5)
print(simple2.value)
// 5
* class 안에 기본 초기화 메소드 init() 없이 init(v: Int)만 있을시 인스턴스화 할 때 인자를 호출하지 않으면 에러가 발생한다
let simple3 = SimpleClass2() // error 발생
// "Missing argument for parameter 'v' in call"
-
function과 같이 init도 호출시 argument 생략 가능하다.( _ )
class SimpleClass {
var value = 0
init(_ v: Int) { // argument 자리에 _ (언더바)
self.value = v
}
init() {
self.value = -999
}
}
let a = SimpleClass(10) // argument 생략하고 인자 호출
// value == 10
- 초기화 시켜줄 매개변수가 여러개 있을 경우 모든 매개변수를 호출시 적어줘야 한다.
class SimpleClass3 {
var value: Int
var name: String
var age: Int
var score: Double
init(v: Int, n: String, a: Int, s: Double) {
self.value = v
self.name = n
self.age = a
self.score = s
}
}
let simple = SimpleClass3(v: 5, n: "maru", a: 2, s: 60.8)
- 상속 시 init도 그대로 상속된다. 또한 init을 오버라이드 할 때 super의 init을 호출하는 것으로 부모의 초기화 메소드를 그대로 이용할 수 있다. (init은 override 시 override를 표기할 필요 없다.)
class AnotherClass: SimpleClass2 {
init() {
super.init()
}
}
var simpleClass2 = AnotherClass()
// instance.value == -999
* 위 예시에서는 super.init() 을 호출하지 않아도 문제가 없겠지만, 상속 시 부모의 초기화 메소드를 호출하지 않으면 대게 문제가 발생할 여지가 높으니 호출해주도록 하자.
- init() 은 override 가 가능하지만, 한 클래스 안에서 자신의 다른 init을 호출하면 에러 발생
class SimpleClass {
var value = 0
init(v: Int) {
self.value = v
}
init() {
self.init(v: -999) // ERROR!
}
}
- convenience 키워드를 사용하여 문제 해결.
-
convenience : 한 init이 다른 init을 호출하는 식으로 init이 여러 단계에 걸쳐 처리(multi-step initialization)해야 할 때 필요한 키워드
class SimpleClass {
var value = 0
init(v: Int) {
self.value = v
}
convenience init() {
self.init(v: -999)
}
}
let simple = SimpleClass()
simple.value == -999
let simple2 = SimpleClass(v: 55)
simple.value == 55
-
init 기본 속성 값(Default Property Values)
- 짧고 명확한 initializer를 만들며 기본 값으로부터 속성의 타입을 추론하도록 만든다. initializer 상속을 쉽게 만드는 이점이 있다.
class DefaultClass {
var value = 0
}
let default1 = DefaultClass()
// default1.value == 0
default1.value = 5
//default.value == 5
-
사용자 정의 초기화(Customizing initialization)
- 하나의 변수에 argument, parameter 를 다르게 설정해 주어 인스턴스화해서 호출 할 때 사용자가 필요한 인자로 설정해서 사용 가능
struct Celsius {
var temperatureInCelsius: Double
init(fromFahrenheit fahrenheit: Double) {
temperatureInCelsius = (fahrenheit - 32.0) / 1.8
}
init(fromKelvin kelvin: Double) {
temperatureInCelsius = kelvin - 273.15
}
init(_ celsius: Double) {
temperatureInCelsius = celsius
}
}
let boilingPointOfWater = Celsius(fromFahrenheit: 212.0)
// boilingPointOfWater.temperatureInCelsius is 100.0
let freezingPointOfWater = Celsius(fromKelvin: 273.15)
// freezingPointOfWater.temperatureInCelsius is 0.0
let bodyTemperature = Celsius(37.0)
// argument 생략
// bodyTemperature.temperatureInCelsius is 37.0
-
Deinitalization
- init의 반대 요소
* deinit은 클래스에서만 사용 가능
- deinit은 parameter를 가질 수 없다.
class SimpleClass {
var value = 0
deinit {
self.value = 0
}
}