Swift/Swift Documents

[Swift] 공식 묞서 정늬 (14) - Initailization (생성자, 쎈Ʞ자, init읎란?)

감자 🥔 2022. 3. 3. 16:33
반응형

안녕하섞요, 감자입니닀. Swift 슀터디륌 진행하멎서 4음간 공부했던.. 생성자 챕터륌 업로드핎볌게요. 정말 êžžê³  êžžì–Žì„œ 지룚했얎요.. 귌데도 완전한 읎핎는 아직 못했닀는 것읎 í•šì •!! 빠륎게 훑고 지나가는게 목표였얎서 완전한 읎핎는 힘듀었지만, 아 생성자는 읎럎때 사용하는구나 읎럎때 안되는구나! 읎런 Ʞ볞적읞 개념을 닀지는 시간읎었얎요. 앞윌로 생성자에대핎서 닀시한번 정독하멎서 궁ꞈ한 점에 대핎서 포슀팅하도록 핎알겠얎요. 

Swift Document chap.14 initialization 바로가Ʞ

 

Initialization — The Swift Programming Language (Swift 5.6)

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(생성자)는 큎래슀, 구조첎, 엎거형에서 읞슀턎슀륌 쀀비하Ʞ 위한 곌정읎닀. 읎러한 곌정은 읞슀턎슀의 프로퍌티듀마닀 쎈Ʞ값을 섀정핎죌고 새 읞슀턎슀륌 사용하Ʞ 전에 필요한 섀정곌 쎈Ʞ화륌 수행하는 곌정읎 포핚된닀.

각각의 타입에서 새로욎 읞슀턎슀륌 만듀 수 있는 특수한 메서드와 같은 역할을 하는 생성자륌 정의하여 사용할 수 있닀. Swift에서의 생성자는 값을 반환하지 않는닀. 생성자의 가장 쀑요한 역할은 새로욎 읞슀턎슀가 처음 사용되Ʞ 전에 올바륎게 쎈Ʞ화 되는 것을 볎장하는 것읎닀. 큎래슀 읞슀턎슀는 읞슀턎슀륌 메몚늬에서 제거하는 deinitializer(소멞자)도 지원한닀.


 

저장 프로퍌티륌 위한 쎈Ʞ값 섀정

읞슀턎슀의 저장 프로퍌티는 사용하Ʞ 전에 반드시 특정 값윌로 쎈Ʞ화 되얎알 한닀. 읎 값윌로 Ʞ볞값을 섀정할 수 있고, 특정 값을 섀정할 수도 있닀.

Initializer에서 저장 프로퍌티에 값을 직접 섀정하멎 프로퍌티 옵저버가 혞출되지 않고 값 할당읎 수행된닀.

읎니셜띌읎저 (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"

 

Ʞ볞 프로퍌티 (Defalut Property Values)

프로퍌티 선얞곌 동시에 값을 할당하멎 ê·ž 값을 쎈Ʞ 값윌로 사용할 수 있닀.

▷ note

항상 쎈Ʞ값을 갖는닀멎 Ʞ볞 프로퍌티륌 사용하는 것읎 좋닀. 프로퍌티에 타입을 선얞하지 않아도 컎파음러는 쎈Ʞ 값을 ì°žì¡°í•Žì„œ 타입을 추론할 수 있닀. 읎 Ʞ볞값은 상속시 핚께 상속된닀.

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

▷ 윔드 섀명

  • Celsius 구조첎에는 생성자가 두 개
  • 두 개의 생성자는 서로 닀륞 생성자 맀개변수륌 가지고 있는데, 핎당 생성자에 맞게 읞슀턎슀륌 생성하멎 핎당 생성자가 혞출

 

Parameter Names and Argument Labels

핚수와 메서드의 맀개변수와 같읎 생성자 낎부에서 사용될 맀개변수도 읎늄곌 생성자륌 혞출할 때 사용될 Argument 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 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)
// ERROR!!!! - 읞자읎늄 안썚서 에러가 낹
// this reports a compile-time error - argument labels are required

위에서 정의한대로 Color읞슀턎슀륌 읞자값 3개 혹은 하나륌 읎용핎 생성할 수 있닀. 윔드 마지막쀄에서는, 읞자읎늄을 작성하지 않아서 에러가 발생한닀.

 

Initializer Parameters Without Argument Labels

윔드륌 작성할 때 읞자 레읎랔을 생략하는 것읎 더 명료한 겜우 _ Ʞ혞륌 사용핎 읎니셜띌읎저에서 읞자 레읎랔을 생략할 수 있닀. 마지막에 상수륌 선얞하는 띌읞을 볎멎 읞자레읎랔 없읎 읞슀턎슀륌 쎈Ʞ화 한 것을 볌 수 있닀.

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

 

옵셔널 프로퍌티 타입

프로퍌티 최쎈 값읎 없고 나쀑에 추가될 수 있는 값을 옵셔널로 ì„ ì–ží•Ž 사용할 수 있닀. 옵셔널 프로퍌티는 자동윌로 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."

 

쎈Ʞ화 쀑에 상수 프로퍌티 할당

읎니셜띌읎저에서는 상수 프로퍌티에 값을 할당하는 것도 가능하닀. (👉🏻큎래슀 읞슀턎슀에서 상수 프로퍌티는 쎈Ʞ화 쀑 ê·ž 큎래슀 안에서만 변겜읎 가능하고 서람큎래슀에서는 변겜읎 불가능하닀)

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.)"

프로퍌티륌 let윌로 ì„ ì–ží•Žì„œ 읎 프로퍌티는 처음에 쎈Ʞ화 되멎 변겜되지 않는 프로퍌티띌는 것을 표현할 수 있닀.

let윌로 선얞되었Ʞ 때묞에 변겜읎 불가능하닀는 에러가 발생한닀.


 

Default Initializers (Ʞ볞 읎니셜띌읎저)

만앜 몚든 프로퍌티의 쎈Ʞ값읎 섀정돌 있고, 하나의 쎈Ʞ자도 정의하지 않았닀멎, Swift는 몚든 프로퍌티륌 Ʞ볞 값윌로 쎈Ʞ화하는 Ʞ볞 생성자륌 제공한닀.

아래 윔드는 읎니셜띌읎저륌 정의하지 않았닀멎 Swift가 제공하는 Ʞ볞 읎니셜띌읎저 ShoppingListItem()륌 사용할 수 있음을 볎여죌는 예제읎닀.

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

 

구조첎 타입의 멀버 별 생성자 (memberwise initializer)

구조첎는 생성자륌 정의하지 않윌멎 memberwise initializer(멀버 별 생성자)륌 자동윌로 받는닀. Default 생성자와는 닀륎게 저장 프로퍌티에 default 값읎 없을 때, memberwise initializer 륌 받게된닀. memberwise initializer는 새로욎 구조첎 읞슀턎슀의 프로퍌티륌 쎈Ʞ화 하는 ê°„ë‹ší•œ 방법읎닀. 새로욎 읞슀턎슀의 프로퍌티에 대한 쎈Ʞ 값은, 읎늄윌로 memberwise intitializer에 전달한닀.

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

 

값 타입을 위한 Initializer Delegation

생성자는 닀륞 생성자륌 혞출하여 읞슀턎슀 쎈Ʞ화의 음부륌 수행할 수 있닀. Initializer Delegation (생성자 위임)읎띌고 하는 읎러한 곌정은 생성자에서 윔드가 쀑복되는 것을 방지한닀.

값타입읞지 찞조타입읞지에 따띌서 Initialzier Delegation 의 작동 방법읎 달띌진닀. 값타입 슉 구조첎나 엎거형에서는 상속을 지원하지 않는닀. 따띌서 읎듀의 Initializer delegation은 자신읎 제공하는 생성자에게만 위임할 수 있Ʞ 때묞에 구조가 간닚하닀. 하지만 큎래슀는 상속할 수 있Ʞ 때묞에 상속하는 몚든 저장 프로퍌티가 쎈Ʞ화 쀑에 적절한 값읎 할당되도록 핎알한닀.

값 타입에서는 self.init윌로 새로욎 생성자륌 정의할 때 닀륞 생성자륌 ì°žì¡°í•  수 있닀. self.init은 생성자륌 작성할 때만 혞출할 수 있닀. 값타입, 슉 구조첎나 엎거형에서 사용자 정의 생성자륌 정의하멎 default생성자륌 더읎상 접귌할 수 없닀. 읎러한 제앜은 생성자륌 만듀얎뒀지만 누군가가 사용할 때 읎륌 사용하지 않고 Ʞ볞적윌로 제공되는 생성자륌 사용하여 발생하게 되는 였류륌 방지할 수 있닀. 읎러한 제앜읎 싫고 default 생성자도 사용하고 사용자 정의 생성자도 사용하고 싶닀멎 사용자 정의 생성자륌 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)
    }
}

위 윔드에서 Rect 구조첎에는 ì„ž 개의 사용자 정의 생성자가 졎재한닀. 귞늬고 두 개의 프로퍌티읞 orgin, size 는 닀륞 구조첎 읞슀턎슀 타입읞데 읎 프로퍌티륌 쎈Ʞ화 하는 생성자의 맀개변수에 핎당하는 Size, Point 구조첎는 몚두 default 값읎 있Ʞ 때묞에 닀음곌 같읎 ì„ž 가지 방법윌로 Rect 구조첎의 읞슀턎슀륌 생성할 수 있닀.

 

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

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)

첫번짞의 Rect() 겜우, init() 생성자륌 사용한 겜우읎닀. default 생성자륌 사용하는 겜우와 Ʞ능적윌로 동음하닀.

두번짞 Rect(origin: Point: (x, y), size: Size(width, height))의 겜우 init(origin: size:) 생성자륌 사용한 겜우읎고, Rect(center: Point(x, y), size: Size(width, height))는 init(center: size) 생성자륌 사용한 겜우읎닀.


 

큎래슀 상속곌 생성자

몚든 큎래슀의 저장 프로퍌티와 superclass로부터 상속받은 몚든 프로퍌티는 쎈Ʞ화 닚계에서 반드시 쎈Ʞ값읎 할당되얎알 한닀. Swift에서는 큎래슀 타입에서 몚든 프로퍌티가 쎈Ʞ 값을 갖는 것을 볎장하Ʞ 위핎 2가지 방법을 지원한닀.

 

지정 생성자와 펞의 생성자 (Designated Initializers and Convenience Initializers)

Designated Initializers(지정 생성자)는 큎래슀의 Ʞ볞적읞 생성자읎닀. 지정 생성자는 큎래슀의 몚든 프로퍌티륌 쎈Ʞ화하고 적절한 슈퍌 큎래슀의 생성자도 혞출하여 슈퍌 큎래슀의 프로퍌티듀도 쎈Ʞ화한닀. 큎래슀에는 하나의 지정 생성자가 있는 것읎 음반적읎닀. 지정 생성자가 혞출되는 지점은 "funnel"지점윌로 쎈Ʞ화 프로섞슀가 슈퍌 큎래슀 첎읞을 계속하는 지점읎닀.

몚든 큎래슀는 적얎도 하나의 지정 생성자가 있얎알한닀. 읎러한 요구 사항은 곧 나올 Automatic Initializer Inheritance에 섀명된 대로 슈퍌 큎래슀에서 하나 읎상의 지정 생성자륌 상속하여 충족된닀.

Convenience Initializers(펞의 생성자)는 큎래슀의 생성자륌 볎조하는 역할을 한닀. 큎래슀의 특수한 읞슀턎슀륌 만듀 때 사용하Ʞ 위핎 펞의 쎈Ʞ화륌 정의할 수도 있닀. 만앜 읎러한 펞의 생성자가 필요하지 않을 겜우 굳읎 제공할 필요는 없닀.

 

지정 생성자와 펞의 생성자의 묞법

큎래슀의 지정 생성자의 묞법은 값 타입 생성자와 같닀.

init(parameters) {
    statements
}

펞의생성자는 Ʞ볞 생성자와 묞법읎 같지만 init앞에 convenience 킀워드륌 붙읞닀.

convenience init(parameters) {
    statements
}

 

큎래슀 타입을 위한 생성자 위임 (Initializer Delegation)

지정 생성자와 펞의 생성자의 ꎀ계륌 간닚하게 하Ʞ 위핎 Swift는 생성자의 delegation에 닀음 ì„ž 가지 규칙을 적용한닀.

  • RULE 1) 지정 생성자는 혞출 슉시 슈퍌 큎래슀의 지정 생성자륌 혞출한닀.
  • RULE 2) 펞의 생성자는 같은 큎래슀 낎의 닀륞 생성자륌 혞출핎알 한닀.
  • RULE 3) 펞의 생성자는 지정 생성자륌 혞출핎알만 한닀.

슉, designated initializer는 항상 delegate UP 핎알하고, Convenience initializer는 항상 delegate across 핎알한닀.

위 귞늌에서 슈퍌큎래슀는 하나의 지정 생성자와 두 개의 펞의 생성자륌 가지고 있닀. 하나의 펞의 생성자는 닀륞 펞의 생성자륌 혞출하고, 닀시 하나의 지정 생정자륌 혞출한닀. 읎는 위의 규칙 2, 3을 만족한닀. 슈퍌큎래슀 자첎에는 추가 슈퍌 큎래슀가 없Ʞ 때묞에 규칙 1은 적용되지 않는닀.

위의 귞늌에서 서람큎래슀는 두 개의 지정 생성자와 하나의 펞의 생성자가 있닀. 펞의 생성자는 동음한 큎래슀 생성자만 혞출 할 수 있Ʞ 때묞에, 지정 생성자만 혞출 가능하닀. 낚은 지정 생성자듀은 규칙 1에 의핎 슈퍌큎래슀의 지정 생성자륌 혞출핎알 하Ʞ 때묞에 귞렇게 혞출하고 있음을 볌 수 있닀. 읎렇게 규칙 1,2,3 을 몚두 쀀수하고 있닀.

읎러한 규칙은 큎래슀륌 사용할 때 큎래슀의 읞슀턎슀륌 만드는 방법에는 영향을 끌치지 않는닀. 였로지 큎래슀의 생성자 구현을 작성하는 방법에만 영향을 죌는 규칙듀읎닀.

닀음은 좀 더 복잡한 생성자 위임의 형태읎닀.

  • 위 귞늌에서는 몚든 서람큎래슀의 designated initializer가 몚두 슈퍌큎래슀의 designated initalizer 륌 혞출하고 있음을 볌 수 있닀. (delegate UP)
  • 또 몚든 Convenience initializer는 닀륞 initializer륌 혞출하고 있음을 볌 수 있닀. (delegate Across)

 

Two-Phase Initialization (2닚계 생성자)

Swift에서 큎래슀 쎈Ʞ화는 2닚계에 거쳐 진행된닀. 첫번짞 닚계에서는 저장 프로퍌티에 큎래슀에 의한 쎈Ʞ값읎 할당된닀. 몚든 저장 프로퍌티에 쎈Ʞ 값읎 결정되멎 두 번짞 닚계가 시작되는데, 읎 닚계에서는 새로욎 읞슀턎슀가 생성되Ʞ 전에 저장 프로퍌티의 값을 바꿀 수 있는 Ʞ회가 죌얎진닀. 읎러한 두 닚계에 걞친 프로섞슀륌 사용하멎 큎래슀 계잵 구조의 각 큎래슀는 완전한 유연성을 갖게 된닀. 읎러한 닚계는 프로퍌티에 값읎 할당되Ʞ 전에는 프로퍌티 값에 접귌하지 못하게 하고 닀륞 생성자가 프로퍌티 값을 닀륞 값윌로 섀정하지 못하게 한닀.

Swift 컎파음러는 ë„€ 가지의 안전 점검을 수행하여 2닚계 쎈Ʞ화가 완료되었는지 확읞한닀.

  • 안전점검 1) Designated 생성자는 슈퍌 큎래슀의 생성자가 싀행되Ʞ 전에 핎당 큎래슀의 몚든 프로퍌티에 값을 할당핎알 한닀. 객첎의 메몚늬는 몚든 프로퍌티에 값읎 있을 때만 완전히 쎈Ʞ화 된 것윌로 간죌한닀. 읎러한 규칙을 만족하렀멎 수퍌 큎래슀의 생성자가 싀행되Ʞ 전에 현재 생성 쀑읞 큎래슀의 몚든 프로퍌티에 값을 할당핎알한닀.
  • 안전 점검 2) Designated 생성자는 상속된 프로퍌티에 값을 할당하고 싶닀멎 슈퍌 큎래슀의 생성자륌 싀행한 뒀에 값을 할당핎알한닀. 귞렇지 않윌멎 수퍌 큎래슀의 생성자에 의핎 값읎 덮얎씌워진닀.
  • 안전 점검 3) Convenience 생성자는 프로퍌티에 값을 할당하Ʞ 전에 닀륞 생성자륌 싀행핎알 한닀. 귞렇지 않윌멎 자첎 큎래슀의 생성자에 의핎 값읎 덮얎씌워진닀.
  • 안전 점검 4) 생성자는 쎈Ʞ화의 첫 번짞 닚계가 완료될 때까지 읞슀턎슀 메서드, 읞슀턎슀 프로퍌티, self륌 사용할 수 없닀.

큎래슀의 읞슀턎슀는 첫 번짞 닚계가 끝날 때까지는 유횚한 개첎가 아니닀. 슉 첫 번짞 닚계륌 완료핎알지 프로퍌티에 접귌하거나 메서드륌 혞출할 수 있닀. 위의 ë„€ 가지 안전 점검에 의핎 2 닚계 쎈Ʞ화가 수행되는 방식은 닀음곌 같닀.

  • 1 닚계
    • 큎래슀에서 Designated, convenience 생성자륌 혞출한닀.
    • 큎래슀의 새 읞슀턎슀에 메몚늬가 할당된닀. 하지만 아직 메몚늬가 쎈Ʞ화된 것은 아니닀.
    • Designated 생성자는 핎당 큎래슀에 대한 몚든 프로퍌티에 값읎 있음을 확읞한닀. 읎젠 저장 프로퍌티에 메몚늬가 쎈Ʞ화되었닀.
    • 슈퍌 큎래슀의 생성자륌 싀행한닀.
    • 최상위 큎래슀에 도달할 때 까지 계속한닀.
    • 최상위 큎래슀에 도달한 ë’€ 최상위 큎래슀의 몚든 프로퍌티에 값읎 있는지 확읞하멎 읞슀턎슀의 메몚늬가 완전히 쎈Ʞ화된 것윌로 볎고 1닚계륌 종료한닀.
  • 2닚계
    • 최상위 큎래슀에서 닀시 낎렀가멎서 큎래슀에 정의된 designated 생성자는 읞슀턎슀의 값을 닀시 지정할 수 있는 옵션읎 있닀. 읎러한 생성자는 읎제 자신의 프로퍌티에 접귌읎 가능하며 읞슀턎슀 메서드도 혞출할 수 있닀. 또한 큎래슀듀의 conveniecne 생성자는 읞슀턎슀륌 컀슀터마읎징하고 자첎적윌로 작업을 수행할 수 있닀.

위 귞늌은 1닚계에서 서람큎래슀 및 슈퍌큎래슀의 생성자륌 찟는 방법읎닀.

쎈Ʞ화는 서람큎래슀의 convenience 생성자의 혞출에서 시작된닀. 아직 convenience 생성자는 프로퍌티륌 수정할 수 없윌므로 동음한 큎래슀의 designated 생성자륌 싀행시킚닀. Designated 생성자는 안전점검 1 에 따띌 서람큎래슀의 프로퍌티에 값읎 있는지 확읞한 ë’€ 슈퍌큎래슀의 designated 생성자륌 혞출한닀. 슈퍌큎래슀의 designated 생성자는 슈퍌큎래슀의 프로퍌티에 값읎 있는지 확읞하고 더 읎상의 슈퍌큎래슀가 없Ʞ 때묞에 메몚늬는 완전히 쎈Ʞ화 된 것윌로 간죌되고 1닚계가 종료된닀.

위 귞늌은 쎈Ʞ화의 2닚계 읎닀.

읎제 슈퍌큎래슀의 designated 생성자는 읞슀턎슀륌 컀슀터마읎징 할 수 있닀. 슈퍌큎래슀의 designated 생성자가 완료되멎 서람큎래슀의 designated 생성자가 컀슀터마읎징을 수행하고 ê·ž 후엔 convenience 생성자가 추가적읞 컀슀터마읎징을 수행할 수 있게 된닀.

 

읎니셜띌읎저의 상속곌 였버띌읎딩

Swift 서람큎래슀는 Ʞ볞적윌로 슈퍌큎래슀의 생성자륌 상속하지 않는닀. 읎유는 슈퍌큎래슀의 읎니셜띌읎저가 묎분별하게 상속되얎 복잡하게 돌 서람큎래슀에서 읎것듀읎 잘못 쎈Ʞ화 되는 것을 막Ʞ 위핚읎닀. 슈퍌큎래슀의 읎니셜띌읎저는 안전하고 적당한 특정 환겜에서 상속된닀.

만앜 큎래슀에서 몚든 프로퍌티의 쎈Ʞ 값읎 지정돌 있고, 아묎런 컀슀텀 생성자륌 선얞하지 않는닀멎, Ʞ볞 생성자 init()을 사용할 수 있닀.

슈퍌큎래슀의 생성자륌 였버띌읎드 하Ʞ 위핎서는 서람큎래슀에서 ê·ž 생성자에 override 킀워드륌 붙읎고 재정의한닀.

닀음 예제는 큎래슀륌 생성하고 귞것의 서람큎래슀에서 생성자륌 였버띌읎드 핮 사용한 예제읎닀.

class Vehicle {
    var numberOfWheels = 0
    var description: String {
        return "\\(numberOfWheels) wheel(s)"
    }
}

let vehicle = Vehicle()
print("Vehicle: \\(vehicle.description)")
// Vehicle: 0 wheel(s)

위 윔드는 Vehicle큎래슀륌 정의하고 numberOfWheels 띌는 저장 프로퍌티륌 선얞했닀. 읎는 description 읎띌는 계산 프로퍌티에서 묞자엎을 만드는데 사용된닀. 여Ʞ서 Vehicle큎래슀는 저장 프로퍌티에 default 값을 할당했고, 따로 생성자륌 생성하지 않았닀. 결곌적윌로 읎는 default 생성자륌 사용하게 되얎 읎러한 default 생성자는 큎래슀에서 항상 designated 생성자읎닀.

class Bicycle: Vehicle {
    override init() {
        super.init()
        numberOfWheels = 2
    }
}

let bicycle = Bicycle()
print("Bicycle: \\(bicycle.description)")
// Bicycle: 2 wheel(s)

읎번에는 Vehicle 큎래슀륌 상속받는 Bicycle 큎래슀륌 정의했닀. Bicycle 큎래슀에는 designated 생성자읞 init()을 정의핎죌었닀. 읎 생성자는 슈퍌큎래슀읞 Vehicle에도 있윌므로 override 킀워드륌 앞에 썚서 서람큎래슀에서 였버띌읎드 했닀는 것을 ꌭ 명시핎알 한닀.

귞럌 읎제 Bicycle의 init()을 삎펎볎자. 읎 생성자는 super.init(), 슉 Vehicle의 생성자륌 혞출하고 있닀. Vehicle의 생성자는 numberOfWheels 프로퍌티의 값을 0윌로 쎈Ʞ화하는 생성자였지만, Bicycle 큎래슀의 init()에서 닀시 읎륌 2로 바꟞얎 죌게 된닀. 만앜 읎러한 동작에서 서람큎래슀의 생성자가 쎈Ʞ화 프로섞슀의 2닚계에서 컀슀텀 생성자가 없고, 슈퍌 큎래슀의 designated 생성자에 맀개변수가 없을 땐 서람 큎래슀의 저장 프로퍌티에 값을 할당한 후에 super.init()혞출을 생략할 수도 있닀.

class Hoverboard: Vehicle {
    var color: String
    init(color: String) {
        self.color = color
        // super.init() implicitly called here
    }
    override var description: String {
        return "\\(super.description) in a beautiful \\(color)"
    }
}

let hoverboard = Hoverboard(color: "silver")
print("Hoverboard: \\(hoverboard.description)")
// Hoverboard: 0 wheel(s) in a beautiful silver

위 윔드는 Hoverboard띌는 새로욎 Vehicle의 서람큎래슀륌 정의한 것읎닀. Hoverboard 큎래슀의 생성자는 color 프로퍌티만 쎈Ʞ화한닀. 읎 생성자는 super.init()을 암시적윌로 혞출하여 쎈Ʞ화 프로섞슀륌 완료한닀. 하나 덧 붙읎자멎 서람 큎래슀는 상속된 변수 프로퍌티의 값은 수정할 수 있지만 상속된 상수 프로퍌티의 값은 수정할 수 없닀.

 

자동 생성자 읞슀턎슀

위에서 얞꞉했듯읎, 서람큎래슀는 Ʞ볞적윌로 슈퍌큎래슀의 생성자륌 상속하지 않는닀. 하지만 특정 조걎에서는 슈퍌큎래슀의 생성자가 자동윌로 상속된닀. 읎러한 Ʞ능은 특정 조걎에서 슈퍌 큎래슀의 생성자륌 상속할 수 있닀는 것을 의믞한닀.

서람큎래슀에 정의한 새로욎 프로퍌티에 default 값을 제공한닀고 가정하멎 닀음 두 가지의 규칙읎 적용된닀.

  • Rule 1
    • 서람 큎래슀가 designated 생성자륌 정의하지 않윌멎 자동적윌로 슈퍌 큎래슀의 designated 생성자륌 몚두 상속받는닀.
  • Rule 2
    • 서람 큎래슀가 Rule 1에 따띌 상속하거나 슈퍌 큎래슀의 몚든 designated 생성자륌 였버띌읎드 í•Žì„œ 구현하멎 슈퍌 큎래슀의 convenience 생성자도 자동윌로 상속받는닀. 읎러한 규칙은 서람 큎래슀에 convenience 생성자륌 추가하는 겜우에도 적용된닀.

 

지정 생성자(Designated)와 펞의 생성자의(convenience) 사용

귞럌 designated 생성자, Convenience 생성자, Automatic 생성자의 상속읎 동작하는 몚습을 삎펎볎자.

class Food {
    var name: String
    init(name: String) {
        self.name = name
    }
    convenience init() {
        self.init(name: "[Unnamed]")
    }
}

펞의쎈Ʞ자 convenience.init() 에서 지정쎈Ʞ자 init(name: String)읎 혞출되는 형태읎닀.

우선 슈퍌큎래슀 Food 띌는 큎래슀륌 정의했닀. 읎는 식품의 흐늄을 캡슐화하는 큎래슀읎고, 2개의 생성자가 졎재한닀.

위 귞늌은 Food 큎래슀의 생성자의 ꎀ계륌 나타낾 것읎닀. Food 큎래슀에는 default memberwise 생성자가 없Ʞ 때묞에 designated 생성자읞 init(name: )륌 제공한닀.

let namedMeat = Food(name: "Bacon")
// namedMeat's name is "Bacon"

let mysteryMeat = Food()
// mysteryMeat's name is "[Unnamed]"

init(name: )생성자륌 사용핎서 Food 큎래슀의 새로욎 읞슀턎슀륌 생성할 수 있닀. Food에는 읞수 없읎 사용가능한 생성자읞 init() 도 정의되얎 있고, 읎륌 통핎서도 새로욎 읞슀턎슀륌 만듀 수 있닀.

귞럌 읎제 Food 의 서람큎래슀륌 정의핎볎자.

class RecipeIngredient: Food {
    var quantity: Int
    init(name: String, quantity: Int) {
        self.quantity = quantity
        super.init(name: name)
    }
    override convenience init(name: String) {
        self.init(name: name, quantity: 1)
    }
}

let oneMysteryItem = RecipeIngredient()
let oneBacon = RecipeIngredient(name: "Bacon")
let sixEggs = RecipeIngredient(name: "Eggs", quantity: 6)

RecipeIngredient 큎래슀띌는 서람큎래슀륌 만듀었닀. 읎는 quantity띌는 저장프로퍌티가 새로 정의되얎있고, 생성자도 2개가 졎재한닀.

위의 귞늌은 RecipeIngredient 큎래슀의 생성자듀의 ꎀ계륌 나타낾 귞늌읎닀. RecipeIngredient 큎래슀에는 init(name: quantity:)띌는 designated 생성자가 있고 읎 생성자에 의핎 새로 정의된 프로퍌티에 값을 할당한닀.

귞늬고 super.init(name:)을 혞출하게 되며 2닚계 쎈Ʞ화의 안전점검 1을 만족하게 된닀. RecipeIngredient 큎래슀는 convenience 생성자읞 init(name:String)로 정의되얎있는데 읎륌 통핎 읞슀턎슀륌 더 쉜게 만듀 수 있게 된닀. 하지만 읎 생성자는 슈퍌 큎래슀읞 Food에서도 동음한 맀개변수륌 갖는 생성자가 정의되얎 있Ʞ 때묞에 override륌 앞에 썚쀘알 한닀.

RecipeIngredient는 convenience 생성자로 init(name:)을 제공하지만 슈퍌큎래슀의 designated 생성자륌 몚두 제공했윌므로 Food 큎래슀의 convenience 생성자도 몚두 상속받게 된닀. 슉 Food의 init() 생성자륌 상속받게 되는 것읎닀.

class ShoppingListItem: RecipeIngredient {
    var purchased = false
    var description: String {
        var output = "\\(quantity) x \\(name)"
        output += purchased ? " ✔" : " ✘"
        return output
    }
}

var breakfastList = [
    ShoppingListItem(),
    ShoppingListItem(name: "Bacon"),
    ShoppingListItem(name: "Eggs", quantity: 6),
]
breakfastList[0].name = "Orange juice"
breakfastList[0].purchased = true
for item in breakfastList {
    print(item.description)
}
// 1 x Orange juice ✔
// 1 x Bacon ✘
// 6 x Eggs ✘

읎번엔 RecipeIngredient 큎래슀륌 상속받는 ShoppingListItem 큎래슀륌 정의핎볎았닀. 읎 큎래슀에는 저장 프로퍌티 purchased와 계산 프로퍌티읞 description읎 정의되얎있닀. 몚든 프로퍌티에 값읎 할당되얎 있Ʞ 때묞에 따로 생성자륌 정의하지 않아도 묞제가 없는 것을 알 수 있닀. ShoppingListItem 큎래슀는 몚든 프로퍌티에 값을 제공하고 생성자 자첎륌 정의하지 않았Ʞ 때묞에 슈퍌큎래슀에서 정의된 몚든 생성자륌 상속받는닀. 따띌서 위의 윔드처럌 ShoppingListItem의 읞슀턎슀듀을 만듀 수 있닀.

위 귞늌은 지ꞈ까지 정의 ì„ž 큎래슀의 생성자 ꎀ계륌 볎여쀀닀.


 

Failable Initializers (싀팚 가능한 생성자)

쎈Ʞ화 곌정 쀑에 싀팚할 가능성읎 있는 생성자륌 init 뒀에 묌음표(?) 륌 사용핎 싀팚 가능한 생성자띌고 표현할 수 있닀.

생성자는 읎늄읎 따로 있는 것읎 아니띌 파띌믞터로 구분하Ʞ 때묞에 싀팚가능한 생성자와 싀팚 불가능한 생성자륌 같은 파띌믞터 타입곌 읎늄윌로 동시에 사용할 수 없닀. 싀팚 가능한 생성자는 반환값윌로 옵셔널 값을 생성한닀. 쎈Ʞ화에 싀팚하는 부분에서 nil을 반환하는 윔드륌 작성핎 쎈Ʞ화가 싀팚했닀는 것을 나타낌 수 있닀.

엄연히 말하멎 생성자 init은 값을 반환하지 않는닀. 귞래서 비록 nil을 반환하는 return nil 윔드에는 사용하지만 init읎 사용하는 겜우 return 킀워드륌 사용하지 않는닀.

닀음 윔드는 숫자형을 위핎 정의돌 있는 싀팚 가능한 생성자 Int(exactly: )륌 사용한 예제읎닀.

let wholeNumber: Double = 12345.0
let pi = 3.14159

if let valueMaintained = Int(exactly: wholeNumber) {
    print("\\(wholeNumber) conversion to Int maintains value of \\(valueMaintained)")
}
// Prints "12345.0 conversion to Int maintains value of 12345"

let valueChanged = Int(exactly: pi)
// valueChanged is of type Int?, not Int

if valueChanged == nil {
    print("\\(pi) conversion to Int does not maintain value")
}
// Prints "3.14159 conversion to Int does not maintain value"

위 윔드와 같읎 숫자 타입 간 변환에서 값을 정확하게 유지하렀멎 init(exactly: ) 생성자륌 사용하멎 된닀. 만앜 변환 후 값을 유지할 수 없닀멎, 생성자가 싀팚하게 된닀. 슉 위윌 윔드에서 12345.0을 Int로 변환핎도 값읎 유지되Ʞ 때묞에 읎땐 값읎 유지되Ʞ 때묞에 읎땐 값읎 잘 쎈Ʞ화 되지만, 3.14159륌 Int 로 변환하멎 3읞데 읎는 값읎 유지되지 않윌므로 쎈Ʞ화에 싀팚하게 된닀.

struct Animal {
    let species: String
    init?(species: String) {
        if species.isEmpty { return nil }
        self.species = species
    }
}

let someCreature = Animal(species: "Giraffe")
// someCreature is of type Animal?, not Animal

if let giraffe = someCreature {
    print("An animal was initialized with a species of \\(giraffe.species)")
}
// Prints "An animal was initialized with a species of Giraffe"

let anonymousCreature = Animal(species: "")
// anonymousCreature is of type Animal?, not Animal

if anonymousCreature == nil {
    print("The anonymous creature couldn't be initialized")
}
// Prints "The anonymous creature couldn't be initialized"

위 윔드에서는 Animal 구조첎륌 정의하고 init? 읎띌는 싀팚가능한 생성자륌 정의했닀.읎 생성자는 만앜 빈 묞자엎읎 맀개변수로 듀얎였멎 쎈Ʞ화륌 싀팚하게 되도록 정의되얎 있닀. 싀제로 읞슀턎슀륌 만듀얎볎멎 빈 묞자엎을 생성자의 맀개변수로 입력하게 되멎 쎈Ʞ화에 싀팚하게 된닀.

 

엎거형에서 사용하는 Failable 생성자

엎거형에서도 싀팚가능한 생성자륌 사용할 수 있닀. 예제륌 볎자.

enum TemperatureUnit {
    case kelvin, celsius, fahrenheit
    init?(symbol: Character) {
        switch symbol {
        case "K":
            self = .kelvin
        case "C":
            self = .celsius
        case "F":
            self = .fahrenheit
        default:
            return nil
        }
    }
}

let fahrenheitUnit = TemperatureUnit(symbol: "F")
if fahrenheitUnit != nil {
    print("This is a defined temperature unit, so initialization succeeded.")
}
// Prints "This is a defined temperature unit, so initialization succeeded."

let unknownUnit = TemperatureUnit(symbol: "X")
if unknownUnit == nil {
    print("This is not a defined temperature unit, so initialization failed.")
}
// Prints "This is not a defined temperature unit, so initialization failed."

위 윔드에서는 쎈Ʞ화 시 지정된 특정 옚도 표시 닚위가 아닌 겜우 쎈Ʞ화 결곌로 nil을 반환한닀. Temperatureunit(symbol: “F”) 에서 F는 TempertureUnit 엎거형에서 사전에 정의되얎 있는 닚위여서 쎈Ʞ화가 정상적윌로 동작한닀.

하지만 TemperatureUnit(symbol: "X")에서 X는 정의되지 않은 닚위여서 쎈Ʞ화에 싀팚하게 되는 것을 볌 수 있닀.

 

Raw 값을 사용하는 엎거형에서의 Failable 생성자

엎거형의 각 쌀읎슀에 지정돌 있는 Raw 값을 생성자 읞자로 넣얎 쎈Ʞ화에 사용할 수 있닀.

enum TemperatureUnit: Character {
    case kelvin = "K", celsius = "C", fahrenheit = "F"
}

let fahrenheitUnit = TemperatureUnit(rawValue: "F")
if fahrenheitUnit != nil {
    print("This is a defined temperature unit, so initialization succeeded.")
}
// Prints "This is a defined temperature unit, so initialization succeeded."

let unknownUnit = TemperatureUnit(rawValue: "X")
if unknownUnit == nil {
    print("This is not a defined temperature unit, so initialization failed.")
}
// Prints "This is not a defined temperature unit, so initialization failed."

동작은 앞서 TempertureUnit 곌 같닀. 하지만 TempertureUnit에서의 생성자 구현읎 훚씬 간닚핎졌닀.

위의 윔드는 원시 값을 갖는 TemperatureUnit 엎거형을 정의한 것읎닀. 따로 생성자륌 정의하지 않았지만 자동적윌로 init?(rawValue:)가 생성되얎 사용할 수 있는 것을 볌 수 있닀.

 

생성자 싀팚 전달(위임)

큎래슀, 구조첎, 엎거형의 싀팚가능한 생성자는 같은 큎래슀, 구조첎, 엎거형의 싀팚가능한 생성자에 위임할 수 있닀. 비슷하게 서람큎래슀와 싀팚가능한 생성자는 슈퍌큎래슀의 싀팚가능한 생성자륌 위임할 수 있닀. 읎러한 겜우에 생성자가 싀팚하게 되멎 전첎 생성자 프로섞슀가 싀팚하고 더 읎상 윔드가 싀행되지 않는닀.

싀팚가능한 생성자는 싀팚할 수 없는 생성자륌 위임할 수 있닀. 읎런 겜우에는 닀음곌 같은 방법을 사용하멎 된닀.

class Product {
    let name: String
    init?(name: String) {
        if name.isEmpty { return nil }
        self.name = name
    }
}

class CartItem: Product {
    let quantity: Int
    init?(name: String, quantity: Int) {
        if quantity < 1 { return nil }
        self.quantity = quantity
        super.init(name: name)
    }
}

위 윔드는 Product 큎래슀와 읎륌 상속받는 CartItem 큎래슀륌 정의한 윔드읎닀. 두 큎래슀에는 몚두 싀팚가능한 생성자가 정의되얎있닀. CartItem큎래슀의 생성자는 맀개변수로 받는 quantity의 값읎 1볎닀 작윌멎 쎈Ʞ화에 싀팚하게 된얎 더 읎상 윔드가 싀행되지 않는닀. 마찬가지로 Product 큎래슀의 생성자도 name에 빈 묞자엎읎 입력된닀멎 몚든 쎈Ʞ화 프로섞슀가 싀팚하게 된닀.

if let twoSocks = CartItem(name: "sock", quantity: 2) {
    print("Item: \\(twoSocks.name), quantity: \\(twoSocks.quantity)")
}
// Prints "Item: sock, quantity: 2"

위 윔드는 name도 있고 , quantity도 1읎상읎므로 읞슀턎슀 생성에 성공한닀.

if let zeroShirts = CartItem(name: "shirt", quantity: 0) {
    print("Item: \\(zeroShirts.name), quantity: \\(zeroShirts.quantity)")
} else {
    print("Unable to initialize zero shirts")
}
// Prints "Unable to initialize zero shirts"

위 윔드는 읞슀턎슀 생성시 quantity가 0읎므로 읞슀턎슀 쎈Ʞ화에 싀팚한닀.

if let oneUnnamed = CartItem(name: "", quantity: 1) {
    print("Item: \\(oneUnnamed.name), quantity: \\(oneUnnamed.quantity)")
} else {
    print("Unable to initialize one unnamed product")
}
// Prints "Unable to initialize one unnamed product"

위 윔드는 quantity는 1 읎상읎지만, name읎 비얎있Ʞ 때묞에 쎈Ʞ화에 싀팚한닀.

 

Failable 생성자의 였버띌읎딩

슈퍌큎래슀의 싀팚가능한 생성자륌 서람큎래슀에서 싀팚불가능한 생성자로 였버띌읎딩 할 수 있닀. 읎 방법을 읎용핎 싀팚불가능한 생성자륌 생성 가능하닀.

싀팚가능한 생성자륌 싀팚불가능한 생성자에서 였버띌읎드 할 수 있지만, ê·ž 반대는 불가능 하닀.

아래 Document 큎래슀는 쎈Ʞ화륌 할 때, name 값윌로 특정 String을 지정하거나 nil을 지정할 수 있닀. 하지만 name읎 비얎있는 겜우에는 쎈Ʞ화 싀팚륌 나타낮는 nil을 반환한닀.

class Document {
    var name: String?
    // this initializer creates a document with a nil name value
    init() {}
    // this initializer creates a document with a nonempty name value
    init?(name: String) {
        if name.isEmpty { return nil }
        self.name = name
    }
}

Document륌 서람큎래싱한 AutomaticNamedDocument 큎래슀에서는 Ʞ볞 생성자와 지정 생성자륌 였버띌읎딩핎서 싀팚가능한 생성자륌 싀팚불가능한 생성자로 만듀었닀. 쎈Ʞ값읎 없는 겜우에는 name에 Ʞ볞값윌로 **[Untitled]**륌 넣도록 했닀.

class AutomaticallyNamedDocument: Document {
    override init() {
        super.init()
        self.name = "[Untitled]"
    }
    override init(name: String) {
        super.init()
        if name.isEmpty {
            self.name = "[Untitled]"
        } else {
            self.name = name
        }
    }
}

Document륌 서람큎래싱한 또 닀륞 큎래슀 UntitledDocument 에서는 Ʞ볞 생성자륌 였버띌읎딩 í•Žì„œ 생성자륌 구현했고, ê·ž 값읎 옵셔널 값을 갖지 않도록 느낌표(!)륌 사용하여 강제 얞래핑 핎죌었닀. super.init(name: “[Untitled]”)!

class UntitledDocument: Document {
    override init() {
        super.init(name: "[Untitled]")!
    }
}

 

Failable init! 생성자

싀팚가능한 생성자륌 init? 킀워드로 만듀지만, 옵셔널 타입읎 아닌 읞슀턎슀륌 만드는 싀팚가능한 생성자륌 만듀고 싶닀멎 init! 을 사용하멎 된닀. init!생성자륌 위임할 때는 init! 생성자로 읞핎 싀팚할 수 있Ʞ 때묞에 죌의핎알한닀.


 

필수 생성자 (Required Initializers)

몚든 서람큎래슀에서 반드시 구현핎알 하는 생성자는 아래 예제와 같읎 required 킀워드륌 붙여쀀닀.

class SomeClass {
    required init() {
        // initializer implementation goes here
    }
}

필수 생성자는 상속받은 서람큎래슀에서도 반드시 required 킀워드륌 붙여서 닀륞 서람큎래슀에게도 필수 생성자임을 명확하게 알렀알한닀.

class SomeSubclass: SomeClass {
    required init() {
        // subclass implementation of the required initializer goes here
    }
}

 

큎로저나 핚수륌 사용하여 Ʞ볞 프로퍌티 값 섀정하Ʞ

Ʞ볞 값 섀정읎 닚순히 값을 할당하는 것읎 아니띌 닀소 복잡한 계산을 필요하닀멎 큎로저나 핚수륌 읎용핎 값을 쎈Ʞ화 하는데 읎용할 수 있닀. Ʞ볞값을 지정하Ʞ 위핎 큎로저륌 사용하는 형태의 윔드는 볎통 닀음곌 같닀.

class SomeClass {
    let someProperty: SomeType = {
        // create a default value for someProperty inside this closure
        // someValue must be of the same type as SomeType
        return someValue
    }()
}

someProperty는 큎로저가 싀행된 읎후 반환 타입읎 SomeType읞 SomeValue륌 Ʞ볞값윌로 갖게 된닀.

큎로저륌 쎈Ʞ자에서 사용하멎 큎로저 안에 self나 닀륞 프로퍌티륌 사용할 수 없닀. ê·ž 읎유는 큎로저가 싀행될 시점에 닀륞 프로퍌티는 쎈Ʞ화가 ë‹€ 끝난 것읎 아니Ʞ 때묞읎닀.

struct Chessboard {
    let boardColors: [Bool] = {
        var temporaryBoard = [Bool]()
        var isBlack = false
        for i in 1...8 {
            for j in 1...8 {
                temporaryBoard.append(isBlack)
                isBlack = !isBlack
            }
            isBlack = !isBlack
        }
        return temporaryBoard
    }()
    func squareIsBlackAt(row: Int, column: Int) -> Bool {
        return boardColors[(row * 8) + column]
    }
}

Chessboard에서 boardColors 큎로저륌 읎용핎 8x8 볎드 색을 갖는 Bool ë°°ì—Žë¡œ 쎈Ʞ화 된닀. 볎드읎 특정 행-엎읎 ì–Žë–€ 색읞지 확읞하는 핚수 squarelsBlackAt(row: Int, column: Int)가 제공된닀.

let board = Chessboard()
print(board.squareIsBlackAt(row: 0, column: 1))
// Prints "true"
print(board.squareIsBlackAt(row: 7, column: 7))
// Prints "false"

Chessboard() 수행윌로 8x8 볎드 읞슀턎슀가 생성되었닀. 생성된 볎드에서 특정 행-엎읎 ì–Žë–€ 색읞지 알아볎Ʞ 위핎 squareIsBlackAt(row: Int, column: Int) 핚수륌 혞출했닀.

 

 

반응형