Swift Initialization
* 스스로 공부 및 정리를 위해 The Swift Language Guide을 요약 및 정리 한 내용입니다.
정의
- 초기화는 클래스, 구조체, 열거형 인스턴스를 사용하기 위해 준비 작업을 하는 단계입니다.
- 각 저장 프로퍼티의 초기값을 설정합니다.
- 초기화 과정은 initalizer를 정의 하는것으로 구현할수 있습니다.
- Swift의 initializer는 값을 반환하지 않습니다.
저장 프로퍼티를 위한 초기값 설정 (Setting Initial Value for Stored Property)
- 저장 프로퍼티는 사용하기 전에 반드시 특정 값으로 초기화 돼야합니다.
- 이 값을 기본값으로 설정할수 있고, 특정 값을 설정할수도 있습니다.
- 값을 직접 설정하면 프로퍼티 옵저버가 호출되지 않고 값 할당이 수행됩니다.
이니셜라이즈 (Initalizer)
- 이니셜라이저는 특정 타입의 인스턴스를 생성합니다.
- 가장 간단한 형태는 파라미터가 없고 init 키워드를 사용합니다
- 형태는 init(){}입니다.
struct Animals {
var name: String
init() {
name = "Cat"
}
}
var Cat = Animals()
print(Cat.name)
기본프로퍼티 (Dafault Property Value)
- 프로퍼티 선언과 동시에 값을 할당하면 그값을 초기값으로 사용할수 있습니다.
- 이떄까지 평소에 사용하던 방식입니다.
- 항상 초기값을 갖는 다면 기본 프로퍼티를 사용하는것이 좋습니다.
- 상속시 같이 상속됩니다.
커스터마이징 초기화 (Customizing Initialization)
- 초기화 프로세스를 입력 값과 옵셔널프로퍼티 타입 혹은 상수 값을 할당해서 커스터마이증 할수 있습니다.
초기화 파라미터(Initialization Parameter)
- 초기화 파라미터를 정의해 사용할수 있습니다.
struct Celsius {
var temperatureInCelsius: Double
init(fromFahrenheit fahrenheit: Double){
temperatureInCelsius = (fahrenheit - 32.0) / 1.8
}
init(fromKelvin kelvin: Double){
temperatureInCelsius = kelvin - 273.15
}
}
let boilingPointOfWater = Celsius(fromFahrenheit: 212.0)
let freezingPointOfWater = Celsius(fromKelvin: 273.15)
파라미터 이름과 인자 레이블 (Parameter Name and Arguement Label)
- 메소드와 초기화 모두 파라미터 이름과 인자 레이블을 가지지만, 초기화파라미터는 특정메소드에서 지정하는 메소드 이름을 지정하지 않고, 초기화 식별자로 파라미터를 사용 합니다.
- 사용자가 이 레이블을 지정하지 않으면 Swift가 자동으로 하나를 할당해 제공합니다 * 예시는 초기화 파라미터를 3개 입력받는 초기화와 하나만 입력받는 초기화입니다.
struct Color {
let red, green, blue: Double
init(red: Double, green: Double, blue: Double){
self.red = red
self.green = green
self.blue = blue
}
init(white: Double){
red = white
green = white
blue = white
}
let baseColor = Color(red: 1, green: 1, blue: 1)
let whiteColor = Color(white: 1)
let baseColor = Color(1,1,1)// 인자가 없기 떄문에 에러가 발생합니다.
}
인자 레이블이 없는 이니셜라이저 파라미터 (Initializer Parameter Without Argument Label)
- “_” 기호를 사용해서 인자 레이블을 생략할수 있습니다.
struct Color {
let red, green, blue: Double
init(_ red: Double, _ green: Double, _ blue: Double){
self.red = red
self.green = green
self.blue = blue
}
init(white: Double){
red = white
green = white
blue = white
}
}
let baseColor = Color(1,1,1)
옵셔널 프로퍼티 타입 (Optional Property Type)
- 옵셔널을 사용해서 최초에 값이 없고 나중에 추가할수 있도록 만듭니다. 옵셔널 특징상 자동으로 값이없으면 nil로 초기화됩니다.
class SurveyQuestion {
var text: String
var response: String?
init(text: String) {
self.text = text
}
func ask() {
print(text)
}
}
let cheeseQuestion = SurveyQuestion(text: "Do you like cheese?")
cheeseQuestion.ask()
초기화 중에 상수 프로퍼티 할당 (Assigning Constant Property During Initializtion)
- 초기화는 상수 프로퍼티에 값을 할당하는 것이 가능합니다.
- 단, 그 클래스에서만 가능하고 서브클래스에서는 변경이 안됩니다.
- 결국, 상수는 처음에 초기화 되면 그 값으면 변경되지 않는 프로터피인게 됩니다.
class SurveyQuestion {
let text: String
var response: String?
init(text: String) {
self.text = text
}
func ask() {
print(text)
}
func answer(){
print(response)
}
}
let cheeseQuestion = SurveyQuestion(text: "Do you like cheese?")
cheeseQuestion.ask()
cheeseQuestion.response = "Yes"
cheeseQuestion.answer()
기본 이니셜라이저 (Default Initializer)
- 모든 프로퍼티의 초기값이 설정돼 있고, 하나의 초기자도 정하지 않았다면 Swift는 모든 프로퍼티를 기본값으로 초기화 하는 기본 초기자를 제공합니다.
class Animals {
var name: String?
var numberOfLegs = 1
var Live = true
}
var cat = Animals()
cat.name = "cat"
cat.numberOfLegs = 4
print(cat.name)
print(cat.numberOfLegs)
print(cat.Live)
구조체 타입을 위한 멤버쪽 이니셜라이저 (Memberwise Initializer for Structure Type)
- 맴버쪽 이니셜라이저는 프로퍼티가 기본 값이 없어도 커스텀 이니셜라이저를 정의하지 않았다면 멤버쪽 이니셜라이저를 제공해 줍니다.
- 이 초기자는 선언한 모든 프로퍼티를 인자로 사용합니다.
struct NoteBook{
var width = 0.0, height = 0.0, price = 1000
}
let monnaNoteBook = NoteBook(width: 30, height: 20, price: 500)
print(monnaNoteBook)
값 타입을 위한 이니셜라이저 위임 (Initializer Delegation for Value Type)
- 이니셜라이저에서 다른 이니셜라이저를 호출할수 있습니다.(이니셜나리저 위임)
- 값 타입은 자기자신의 다른 이니셜라이저에서만 사용할수있습니다. (상속불가)
- clsss타입은 superclass의 이니셜라이저를 subclass에서 호출 가능합니다 (상속가능)
- 커스텀 이니셜라이저 선언시 기본 이니셜라이저 혹은 멤버쪽 이니셜라이저를 사용할수 없습니다.
- 2번째 init을 3번째 init에서 불려와 사용하는 예시입니다.
struct Size {
var width = 0.0, height = 0.0
}
struct Point {
var x = 0.0, y = 0.0
}
struct Rect {
var origin = Point()
var size = Size()
init() {}
init(origin: Point, size: Size){
self.origin = origin
self.size = size
}
init(center: Point, size: Size){
let originX = center.x - (size.width / 2 )
let originY = center.x - (size.height / 2 )
self.init(origin: Point(x: originX,y: originY), size: size)
}
}
print(Rect.init())
print(Rect.init(origin: Point(x: 4, y: 4), size: Size(width: 4, height: 4)))
print(Rect.init(center: Point(x: 4, y: 4), size: Size(width: 4, height: 4)))