-
[Apple Dev Reference - Advanced Swift] Initialization (1)앱등이에게 살충제를 뿌린다./Apple Dev Reference 2016. 10. 24. 23:55
<iphone7() 을 해봤자 money == 0이기 때문에 nil이 리턴된다. 이런 경우 failable initializer를 사용해야 한다.>
Initialization은 Class, Structure, Enumeration의 인스턴스를 만드는 과정을 말한다. 이 과정에서 프로퍼티의 값을 초기화하거나 초기화에 필요한 작업을 수행하게 된다.
이러한 작업은 개발자가 initializer를 구현하여 수행할 수 있다. initializer는 조금 특별한 메소드라고 생각할 수 있는데, 클래스의 인스턴스나 구조체 등을 만들 때 호출된다. Objective-C의 initializer와 달리 Swift의 initializer는 리턴 값이 없다. 그저 인스턴스를 사용하기 전에 객체에 대한 초기화를 수행할 뿐이다.
Class객체는 deinitializer를 구현할 수도 있다. deinitializer는 인스턴스가 메모리에서 해제되기 전에 호출된다. 이 또한 개발자가 커스텀하게 구현할 수 있다. deinitializer에 대해서 더 궁금한점은 Deinitialization궁에서 확인하길 바란다.
Setting Initial Values for Stored Properties
Class와 Structure는 초기화 작업이 끝나기 전에 반드시 모든 프로퍼티의 값이 셋팅되어야 한다. 프로퍼티가 indeterminate인 상태로는 인스턴스를 생성할 수 없다.
initializer에서 프로퍼티의 값을 설정할 수도 있고, 프로퍼티를 선언할 때 직접 설정할 수도 있다. 아래에 이 과정을 설명하도록 하겠다.
Note
프로퍼티에 초기값을 설정할 때, 프로퍼티 값의 셋팅은 프로퍼티 옵저버를 호출하지 않고 다이렉트로 셋팅된다.
Initializers
Initializer는 새로운 인스턴스를 만들 때 생성된다. initializer는 일반적인 인스턴스 메소드의 형태와 비슷한데, 가장 간단한 형태는 파라미터를 받지 않는 init키워드만 사용하는 형태이다.
아래의 예제는 Fahrenheit structure를 구현하고 있다. temperature라는 하나의 Double타입 프로퍼티를 갖는다.
Fahrenheit structure는 하나의 initializer, init을 구현하고 있다. 파라미터를 받지 않는 initializer이며 내부에서는 temperature를 32.0으로 셋팅하고 있다. (Fahrenheit에서 어는점이라고 하네요..안궁)
Default Property Values
위 예제처럼, initializer에서 프로퍼티의 초기 값을 셋팅할 수 있다. 외에도 프로퍼티를 선언할 때 디폴트 값을 셋팅해주는 방법도 있다.
Note
프로퍼티가 항상 같은 값을 초기 값으로 갖는다면 initializer에서 셋팅하는 것보다 프로퍼티를 선언할 때 값을 초기화 해주는 것이 좋다. 결과는 같지만 프로퍼티 입장에서는 선언과 초기화(프로퍼티의 초기화)가 전자의 경우에 좀더 가까이 일어나게 된다. 이는 initializer를 좀더 깔끔하고 명확하게 만들어주고 선언과 동시에 값을 셋팅하기 때문에 프로퍼티의 타입추론에도 유리하다. 또한 디폴트 initializer의 장점을 살리는데도 유리하고 initializer 상속에도 유리하다. (이는 아래에서 다루게 됩니다.)
temperature프로퍼티의 초기값을 선언과 동시에 셋팅함으로써 Fahrenheit structure를 아래와 같이 간단하게 구현할 수 있다.
Customizing Initialization
옵셔널 값, 상수 파라미터등을 통해서 초기화 과정을 커스터마이징할 수 있다.
Initialization Parameteres
initializer를 선언할 때, initializer의 파라미터를 설정할 수 있다. initializer의 파라미터를 설정하는 방법은 메소드의 파라미터 선언과 동일하다.
아래 예제는 섭씨 온도 정보를 갖는 Celsius구조체의 코드이다. Celsius구조체는 두 개의 커스터마이징한 initializer, init(fromFahrenheit:)과 init(fromKelvin:)를 갖고 있다. 하나는 화씨온도를 통해서 초기화하고, 하나는 켈빈온도를 통해서 초기화하는 initializer이다.
init(fromFahrenheit:)는 External 파라미터 fromFahrenheit와 Local 파라미터 fahrenheit를 받는다.(말이 좀 이상한데 1개의 파라미터를 받는겁니다.) init(fromKelvin:)도 마찬가지로 External 파라미터 fromKelvin와 Local 파라미터 kelvin를 받는다. 두 initializer모두 전달받은 파라미터를 통해서 섭씨온도에 맞게 변환하여 Celsius구조체를 생성한다.
Local and External Parameter Names
메소드의 파라미터와 같이 init메소드의 파라미터도 local name과 external name을 갖는다.
하지만 initializer는 다른 메소드와 달리 메소드의 이름으로 initializer를 식별할 수가 없다. (파라미터만 다를 뿐 전부다 init이니까..) 이 때, initializer의 파라미터의 이름과 타입으로 initializer를 식별해야 한다. 이 때문에, Swift에서는 개발자가 initializer에 external name을 명시하지 않더라도 자동으로 external name이 생성된다.
아래의 예제는 Color구조체의 코드이다. Color구조체에는 red, green, blue 세 가지 프로퍼티(rgb색을 표현하기 위한 프로퍼티)가 있고, 각 프로퍼티에는 0.0 - 1.0 사이의 값을 갖는다.
Color구조체는 세 파라미터를 받는 initializer와 하나의 파라미터를 받는 initializer를 갖고 있다.
두 initializer 모두 아래처럼 Color객체를 만드는데 사용할 수 있다.
참고로, 파라미터의 external name을 사용하지 않고 initializer를 사용할 수 없다. 아래처럼 external name을 생략하면 컴파일에러가 발생한다.
Initializer Parameters Without External Names
external name을 정말 사용하기 싫다면 언더바(_)를 사용하여 생략할 수 있다. 아래는 Celsiuis구조체를 다시 구현한 예제이다. 을 사용하여 parameter name 없이 Double타입 값만으로 객체를 생성해줄 수 있다.
Optional Property Types
프로퍼티는 nil이 될 수도 있다. 인스턴스 초기화 과정에서 셋팅되지 않는 프로퍼티일 수도 있고, 또는 특성상 nil을 갖는 프로퍼티일 수도 있다. 이런 타입을 우리는 옵셔널로 선언하고 있는데 옵셔널 타입은 초기화과정에서 자동으로 nil로 셋팅이 된다.
아래의 예제는 SurveyQuestion클래스의 코드이다. SurveyQuestion클래스는 response라는 옵셔널 String타입의 프로퍼티를 갖고 있다.
실제로 어떤 질문에 대한 대답(response)은 질문을 하기전까지 알 수가 없다. 따라서 response프로퍼티는 String?타입으로 선언하는 것이 적절해보인다. response는 cheeseQuestion인스턴스를 만들 때 자동으로 nil값을 갖게 된다.
Assigning Constant Properties During Initialization
초기화 과정에서 상수 프로퍼티를 초기화할 수 있다. 초기화 과정이 끝나기 전에 언제든 상수 프로퍼티를 할당할 수 있다. 한번 설정된 상수 프로퍼티는 다시는 수정할 수 없다.
위에서 본 SurveyQuestion클래스 예제를 아래와 같이 다시 만들었다. text프로퍼티를 var가 아닌 let으로 선언하여 상수 타입으로 사용하도록 했다. 상수 프로퍼티지만 초기화 과정에서 값을 할당할 수 있음을 확인할 수 있다.
Default Initializers
Swift에서, 모든 프로퍼티가 초기 값을 갖고 커스텀 initializer를 제공하지 않는 구조체 및 클래스는 Default Initializer를 갖게 된다. 이 Default Initializer는 구조체/클래스 선언문에 적힌 초기 값으로 할당된 인스턴스를 생성할 뿐이다.
아래 예제는 ShoppingListItem클래스의 예제이다. ShoppingListItem클래스는 name, quantity, purchased프로퍼티가 모두 초기 값을 갖고 있다. (name은 String?이니까 nil을 갖겠죠?)
ShoppingListItem클래스의 모든 프로퍼티가 초기 값을 갖고 있다. 그리고 ShoppingListItem클래스는 super클래스도 없기 때문에 ShoppingListItem클래스는 자동으로 default initializer를 갖게 된다. 따라서 위 예제처럼 ShoppingListItem()를 통해 ShoppingListItem타입 인스턴스를 생성할 수 있다.
Memgberwise Initializers for Structure Types
구조체 타입은 커스텀 initializer를 만들지 않으면 자동으로 memberwise initializer를 갖는다. memberwise initializer는 default initializer와는 달리 프로퍼티가 초기 값을 갖지 않더라도 가질 수 있다.
memberwise initializer는 구조체 인스턴스의 프로퍼티를 편리하게 초기화하게 해주는 initializer이다.
아래 예제는 width와 height를 갖는 Size구조체의 코드이다. 이 구조체는 자동으로 memberwise initializer인 init(width:height:)를 갖게 된다.
(여기까지는 기본적인 내용이었고 2 탄에서는 좀 더 깊이가 있는 내용일 것 같네요.)
2탄 내용
Initializer Delegation for Value Types (such as structure)
Designated Initializer & Convenience Initializer
Failable Initializer
Required Initializer
...
'앱등이에게 살충제를 뿌린다. > Apple Dev Reference' 카테고리의 다른 글
[AVFoundation] About the Asset Model (AVAsset에 관하여) (0) 2018.11.06 [Apple Dev Reference] AVPlayer (0) 2018.11.02 [Apple Dev Reference] Nullability and Objective-C (0) 2016.05.22 [Apple Dev Reference - Swift] Nonescaping Closures (0) 2016.05.22 [Apple Dev Reference - Swift] Strong Reference Cycles for Closures (0) 2016.05.15