Notice
Recent Posts
Recent Comments
Link
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Archives
Today
Total
관리 메뉴

개발자의 삽질

[Swift] Initialization - 1편 본문

Swift

[Swift] Initialization - 1편

uniqueimaginate 2022. 1. 24. 00:37

https://docs.swift.org/swift-book/LanguageGuide/Initialization.html

 

Initialization — The Swift Programming Language (Swift 5.5)

Initialization Initialization is the process of preparing an instance of a class, structure, or enumeration for use. This process involves setting an initial value for each stored property on that instance and performing any other setup or initialization t

docs.swift.org


이번엔 Initialization에 대해 알아보자

Initialization은 class, structure, enumeration 인스턴스를 사용하기 위한 준비 단계이다. 이 과정에서는 stored 프로퍼티를 위한 초기 세팅 과정을 진행하고 새 인스턴스를 사용가능하게 만들기 위해서 필요한 추가적인 초기화 단계를 수행한다.

Objective-C의 생성자와는 다르게 Swift에서는 값을 반환하지 않는다.

Setting Initial Values for Stored Properties

클래스와 구조체를 생성할 때, 반드시 모든 저장 프로퍼티가 적절한 초기값으로 설정되어야 한다.

한가지 알아두어야 할 점은, 기본값을 설정할 때나, 생성자를 이용해 초기값을 설정할 때는, 프로퍼티 옵저버가 호출되지 않는다.

Initializers

특정 타입의 새로운 인스턴스를 생성하기 위해서 생성자가 호출된다. init 키워드를 사용한다.

init() {
    // perform some initialization here
}
struct Fahrenheit {
    var temperature: Double
    init() {
        temperature = 32.0
    }
}
var f = Fahrenheit()
print("The default temperature is \(f.temperature)° Fahrenheit")
// Prints "The default temperature is 32.0° Fahrenheit"

Default Preperty Values

저장 프로퍼티에 생성자를 이용해서 초기값을 세팅할 수도 있지만, 프로퍼티를 정의할 때 바로 세팅할 수도 있다.

struct Fahrenheit {
    var temperature = 32.0
}

Customizing Initialization

Initialization Parameters

생성자에 생성자 파라미터를 제공할 수도 있다.

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)
// boilingPointOfWater.temperatureInCelsius is 100.0
let freezingPointOfWater = Celsius(fromKelvin: 273.15)
// freezingPointOfWater.temperatureInCelsius is 0.0

2개의 생성자 모두 하나의 파라미터를 받고 있다.

Parameter Names and Argument Labels

함수와 메서드 파라미터와 같이, 생성자 파라미터 또한 파라미터 이름과 라벨을 제공해 줄 수 있다. 그러나 생성자 그 자체는 이름을 가질 수 없기 때문에, 생성자 파라미터의 타입과 이름이 중요하다. 따라서 생성자 파라미터에 변수 라벨이 없다면 swift 가 자동으로 생성한다.

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 magenta = Color(red: 1.0, green: 0.0, blue: 1.0)
let halfGray = Color(white: 0.5)
// 여기까지 정상 작동

let veryGreen = Color(0.0, 1.0, 0.0)
// 컴파일 에러 발생! - 변수 라벨이 있어야 한다!!

Initializer Parameters Without Argument Lables

변수 라벨을 사용하고 싶지 않다면 underscore(_) 를 사용하면 된다.

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 bodyTemperature = Celsius(37.0)
// bodyTemperature.temperatureInCelsius is 37.0

Optional Property Types

저장 프로퍼티가 값이 없을 수도 있을 경우에는 옵셔널 타입으로 선언하면 된다.

옵셔널 타입의 프로퍼티들은 자동으로 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()
// Prints "Do you like cheese?"
cheeseQuestion.response = "Yes, I do like cheese."

Assigining Constant Preperties During Initialization

상수 프로퍼티는 초기화 단계에서 값을 할당 할 수 있다. 한번 할당되면 더 이상 변경할 수 없다.

클래스 인스턴스에서, 상수 프로퍼티는 그 프로퍼티를 갖고 있는 클래스에서만 값을 설정할 수 있다
서브 클래스에서 변경 할 수 없다.
class SurveyQuestion {
    let text: String
    var response: String?
    init(text: String) {
        self.text = text
    }
    func ask() {
        print(text)
    }
}
let beetsQuestion = SurveyQuestion(text: "How about beets?")
beetsQuestion.ask()
// Prints "How about beets?"
beetsQuestion.response = "I also like beets. (But not with cheese.)"

Default Initializers

Swift는 구조체와 클래스 모두에게 기본 생성자를 제공한다. 이 때, 모든 프로퍼티에는 기본 값이 있어야 한다.

class ShoppingListItem {
    var name: String?
    var quantity = 1
    var purchased = false
}
var item = ShoppingListItem()

quantity, purchased 는 기본 값이 할당되어 있고, name의 경우 옵셔널이기 때문에 nil로 할당된다.

따라서 위의 경우 swift가 기본 생성자를 통해 인스턴스를 생성했다.

Memberwise Initializers for Structure Types

구조체는 custom 생성자가 없을 때, 자동으로 멤버 생성자를 갖게 된다.

기본 생성자와는 다르게, 구조체의 저장 프로퍼티에 기본 값이 없어도 구조체는 멤버 생성자를 갖게 된다.

멤버 생성자는 구조체 인스턴스 멤버 프로퍼티를 초기화하는 간편한 방법이다. 

struct Size {
    var width = 0.0, height = 0.0
}
let twoByTwo = Size(width: 2.0, height: 2.0)

let zeroByTwo = Size(height: 2.0)
print(zeroByTwo.width, zeroByTwo.height)
// Prints "0.0 2.0"

let zeroByZero = Size()
print(zeroByZero.width, zeroByZero.height)
// Prints "0.0 0.0"

Initializer Delegation for Value Types

생성자는 다른 생성자를 호출할 수 있다. 이를 initializer delegation 이라 한다.

값 타입과 클래스 타입은 서로 다른 initializer delegation 방법이 있다.

값 타입(구조체, 열거형)은 상속을 지원하지 않기 때문에 상대적으로 단순하다. 따라서 오로지 자신이 갖고 있는 다른 생성자를 호출하는데 사용한다.

클래스 타입은 다른 클래스를 상속 받을 수 있기 때문에 다르다. 상속받게 되는 모든 프로퍼티에 대한 책임을 갖기 때문이다. 이러한 문제는 아래에서 다루겠다.

값 타입에서는 self.init 을 통해 같은 타입 내에 있는 다른 생성자를 호출할 수 있다. 또한 self.init 은 생성자 내에서만 호출이 가능하다.

값 타입에서 커스텀 생성자를 정의한다면, 더 이상 기본 생성자(멤버 생성자) 를 사용할 수 없게 된다.

만약 기본생성자와 멤버 생성자, 커스텀 생성자를 모든 쓰고 싶다면 커스텀 생성자를 extension 에 작성하자!
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.y - (size.height / 2)
        self.init(origin: Point(x: originX, y: originY), size: size)
    }
}

init(){}

Size(width: 0, height: 0), Point(x: 0.0, y: 0.0) 을 만드는 기본생성자를 호출한다.

let basicRect = Rect()
// basicRect's origin is (0.0, 0.0) and its size is (0.0, 0.0)

init(origin: Point, size: Size) {...}

이는 구조체의 멤버 생성자와 동일한 역할을 한다.

let originRect = Rect(origin: Point(x: 2.0, y: 2.0),
                      size: Size(width: 5.0, height: 5.0))
// originRect's origin is (2.0, 2.0) and its size is (5.0, 5.0)

init(center: Point, size: Size) {...}

self.init 을 통해 다른 생성자에게 위임한다.(delegate)

let centerRect = Rect(center: Point(x: 4.0, y: 4.0),
                      size: Size(width: 3.0, height: 3.0))
// centerRect's origin is (2.5, 2.5) and its size is (3.0, 3.0)

 

 

다음 편 보기

 

2022.01.27 - [Swift] - [Swift] Initialization - 2편 (Class Inheritance & Initialization)

 

[Swift] Initialization - 2편 (Class Inheritance & Initialization)

https://docs.swift.org/swift-book/LanguageGuide/Initialization.html Initialization — The Swift Programming Language (Swift 5.5) Initialization Initialization is the process of preparing an instance..

uniqueimaginate.tistory.com

 

Comments