Potato
์•ˆ๋…•ํ•˜์„ธ์š”, ๊ฐ์žก๋‹ˆ๋‹ค?๐Ÿฅ” ^___^ ๐Ÿ˜บ github ๋ฐ”๋กœ๊ฐ€๊ธฐ ๐Ÿ‘‰๐Ÿป

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) ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ–ˆ๋‹ค.

 

 

๋ฐ˜์‘ํ˜•