๐Ÿฆ… Swift

Initialization

Kiwi๐Ÿ’ป 2022. 7. 13. 16:05

์ดˆ๊ธฐํ™”๋Š” ํด๋ž˜์Šค, ๊ตฌ์กฐ์ฒด, ์—ด๊ฑฐํ˜• ์ธ์Šคํ„ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ์ค€๋น„ ์ž‘์—…์„ ํ•˜๋Š” ๋‹จ๊ณ„ ์ด๋‹ค. ์ด ๋‹จ๊ณ„์—์„œ ๊ฐ ์ €์žฅ ํ”„๋กœํผํ‹ฐ์˜ ์ดˆ๊ธฐ ๊ฐ’์„ ์„ค์ •ํ•œ๋‹ค. ์ดˆ๊ธฐํ™” ๊ณผ์ •์€ initializer๋ฅผ ์ •์˜ ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค. Swift์˜ initializer๋Š” ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š๋Š”๋‹ค. ์ดˆ๊ธฐํ™”์™€ ๋ฐ˜๋Œ€๋กœ ์—ฌ๋Ÿฌ ๊ฐ’๊ณผ ์ž์›์˜ ํ•ด์ง€๋ฅผ ์œ„ํ•ด deinitializer๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

์ €์žฅ ํ”„๋กœํผํ‹ฐ๋ฅผ ์œ„ํ•œ ์ดˆ๊ธฐ๊ฐ’ ์„ค์ • (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"

๊ธฐ๋ณธ ํ”„๋กœํผํ‹ฐ

ํ”„๋กœํผํ‹ฐ์˜ ์„ ์–ธ๊ณผ ๋™์‹œ์— ๊ฐ’์„ ํ• ๋‹นํ•˜๋ฉด ๊ทธ ๊ฐ’์„ ์ดˆ๊ธฐ ๊ฐ’์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

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

ํŒŒ๋ผ๋ฏธํ„ฐ ์ด๋ฆ„๊ณผ ์ธ์ž ๋ ˆ์ด๋ธ” (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
    }
}

์ธ์ž ๋ ˆ์ด๋ธ”์ด ์—†๋Š” ์ด๋‹ˆ์…œ๋ผ์ด์ € ํŒŒ๋ผ๋ฏธํ„ฐ (Initializer Parameters Without Argument Labels)

์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ ์ธ์ž ๋ ˆ์ด๋ธ”์„ ์ƒ๋žตํ•˜๋Š” ๊ฒƒ์ด ๋” ๋ช…๋ฃŒํ•œ ๊ฒฝ์šฐ _ ๊ธฐํ˜ธ๋ฅผ ์‚ฌ์šฉํ•ด ์ด๋‹ˆ์…œ๋ผ์ด์ €์—์„œ ์ธ์ž ๋ ˆ์ด๋ธ”์„ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ๋‹ค.

 init(_ celsius: Double) {
        temperatureInCelsius = celsius
    }

์˜ต์…”๋„ ํ”„๋กœํผํ‹ฐ ํƒ€์ž… (Optional Property Types)

ํ”„๋กœํผํ‹ฐ์˜ ์ตœ์ดˆ ๊ฐ’์ด ์—†๊ณ  ๋‚˜์ค‘์— ์ถ”๊ฐ€๋  ์ˆ˜ ์žˆ๋Š” ๊ฐ’์„ ์˜ต์…”๋„๋กœ ์„ ์–ธํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ต์…”๋„ ํ”„๋กœํผํ‹ฐ๋Š” ์ž๋™์œผ๋กœ nil๋กœ ์ดˆ๊ธฐํ™” ๋œ๋‹ค.

์ดˆ๊ธฐํ™” ์ค‘์— ์ƒ์ˆ˜ ํ”„๋กœํผํ‹ฐ ํ• ๋‹น (Assigning Constant Properties During Initialization)

์ด๋‹ˆ์…œ๋ผ์ด์ €์—์„œ๋Š” ์ƒ์ˆ˜ ํ”„๋กœํผํ‹ฐ์— ๊ฐ’์„ ํ• ๋‹นํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•˜๋‹ค.

NOTEโ—๏ธ
ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค์—์„œ ์ƒ์ˆ˜ ํ”„๋กœํผํ‹ฐ๋Š” ์ดˆ๊ธฐํ™” ์ค‘ ๊ทธ ํด๋ž˜์Šค ์•ˆ์—์„œ๋งŒ ๋ณ€๊ฒฝ์ด ๊ฐ€๋Šฅํ•˜๊ณ  ์„œ๋ธŒํด๋ž˜์Šค์—์„œ๋Š” ๋ณ€๊ฒฝ์ด ๋ถˆ๊ฐ€๋Šฅ ํ•ฉ๋‹ˆ๋‹ค.

๊ธฐ๋ณธ ์ด๋‹ˆ์…œ๋ผ์ด์ € (Default Initializers)

๋งŒ์•ฝ ๋ชจ๋“  ํ”„๋กœํผํ‹ฐ์˜ ์ดˆ๊ธฐ๊ฐ’์ด ์„ค์ •๋ผ ์žˆ๊ณ , ์ด๋‹ˆ์…œ๋ผ์ด์ €๋„ ์ •์˜ํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด Swift๋Š” ๋ชจ๋“  ํ”„๋กœํผํ‹ฐ๋ฅผ ๊ธฐ๋ณธ ๊ฐ’์œผ๋กœ ์ดˆ๊ธฐํ™” ํ•˜๋Š” ๊ธฐ๋ณธ ์ด๋‹ˆ์…œ๋ผ์ด์ €๋ฅผ ์ œ๊ณตํ•ด ์ค๋‹ˆ๋‹ค.

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

๊ตฌ์กฐ์ฒด ํƒ€์ž…์„ ์œ„ํ•œ ๋งด๋ฒ„์ชฝ ์ด๋‹ˆ์…œ๋ผ์ด์ € (Memberwise Initializers for Structure Types)

๊ธฐ๋ณธ ์ด๋‹ˆ์…œ๋ผ์ด์ €์™€ ๋‹ค๋ฅด๊ฒŒ ๋งด๋ฒ„์ชฝ ์ด๋‹ˆ์…œ๋ผ์ด์ €๋Š” ํ”„๋กœํผํ‹ฐ๊ฐ€ ๊ธฐ๋ณธ ๊ฐ’์ด ์—†์–ด๋„ ์ปค์Šคํ…€ ์ด๋‹ˆ์…œ๋ผ์ด์ €๋ฅผ ์ •์˜ํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด ๋ฉค๋ฒ„์™€์ด์ฆˆ ์ด๋‹ˆ์…œ๋ผ์ด์ €๋ฅผ ์ œ๊ณตํ•ด ์ค€๋‹ค. ์ด ์ดˆ๊ธฐ์ž๋Š” ์„ ์–ธํ•œ ๋ชจ๋“  ํ”„๋กœํผํ‹ฐ๋ฅผ ์ธ์ž๋กœ ์‚ฌ์šฉํ•œ๋‹ค.

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

๊ฐ’ ํƒ€์ž…์„ ์œ„ํ•œ ์ด๋‹ˆ์…œ๋ผ์ด์ € ์œ„์ž„ (Initializer Delegation for Value Types)

์ด๋‹ˆ์…œ๋ผ์ด์ €์—์„œ ๋‹ค๋ฅธ ์ด๋‹ˆ์…œ๋ผ์ด์ €๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ณผ์ •์„ ์ด๋‹ˆ์…œ๋ผ์ด์ € ์œ„์ž„์ด๋ผ ํ•œ๋‹ค. ๊ฐ’ ํƒ€์ž…(structures, enumerations)๊ณผ ํด๋ž˜์Šค ํƒ€์ž…(class)๊ฐ„ ์ด๋‹ˆ์…œ๋ผ์ด์ € ์œ„์ž„ ๋™์ž‘์ด ๋‹ค๋ฅด๋‹ค. ๊ฐ’ ํƒ€์ž…์€ ์ƒ์†์„ ์ง€์›ํ•˜์ง€ ์•Š์•„ ์ด๋‹ˆ์…œ๋ผ์ด์ €๋ฅผ ์ž๊ธฐ ์ž์‹ ์˜ ๋‹ค๋ฅธ ์ด๋‹ˆ์…œ๋ผ์ด์ €์—๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ฐ˜๋ฉด ํด๋ž˜์Šค ํƒ€์ž…์€ ์ƒ์†์ด ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— superclass์˜ ์ด๋‹ˆ์…œ๋ผ์ด์ €๋ฅผ subclass์—์„œ ํ˜ธ์ถœ ๊ฐ€๋Šฅํ•˜๋‹ค. ์ƒ์† ๋ฐ›์€ ๋ชจ๋“  ํ”„๋กœํผํ‹ฐ์˜ ์ดˆ๊ธฐํ™”๋Š” ์ฑ…์ž„์€ ์ด๋‹ˆ์…œ๋ผ์ด์ €์— ์žˆ๋‹ค. ์ปค์Šคํ…€ ์ด๋‹ˆ์…œ๋ผ์ด์ € ์„ ์–ธ์‹œ ๊ธฐ๋ณธ ์ด๋‹ˆ์…œ๋ผ์ด์ € ํ˜น์€ ๋ฉค๋ฒ„์™€์ด์ฆˆ ์ด๋‹ˆ์…œ๋ผ์ด์ €๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.

์ด๋Ÿฐ ์ œ์•ฝ์ด ์ด๋‹ˆ์…œ๋ผ์ด์ €์˜ ๋ณต์žก์„ฑ์„ ๋‚ฎ์ถฐ์ฃผ๊ณ  ์ด๋‹ˆ์…œ๋ผ์ด์ €๊ฐ€ ์˜๋„ํ•˜์ง€ ์•Š๊ฒŒ ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•ด ์ค€๋‹ค.

ํด๋ž˜์Šค ์ƒ์†๊ณผ ์ดˆ๊ธฐํ™” (Class Inheritance and Initialization)

๋ชจ๋“  ํด๋ž˜์Šค์˜ ์ €์žฅ ํ”„๋กœํผํ‹ฐ์™€ superclass๋กœ๋ถ€ํ„ฐ ์ƒ์†๋ฐ›์€ ๋ชจ๋“  ํ”„๋กœํผํ‹ฐ๋Š” ์ดˆ๊ธฐํ™” ๋‹จ๊ณ„์—์„œ ๋ฐ˜๋“œ์‹œ ์ดˆ๊ธฐ๊ฐ’์ด ํ• ๋‹น๋ผ์•ผ ํ•œ๋‹ค. Swift์—์„œ๋Š” ํด๋ž˜์Šค ํƒ€์ž…์—์„œ ๋ชจ๋“  ํ”„๋กœํผํ‹ฐ๊ฐ€ ์ดˆ๊ธฐ ๊ฐ’์„ ๊ฐ–๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด 2๊ฐ€์ง€ ๋ฐฉ๋ฒ•์„ ์ง€์›ํ•œ๋‹ค.

์ง€์ • ์ƒ์„ฑ์ž์™€ ํŽธ์˜ ์ƒ์„ฑ์ž ๋ฌธ๋ฒ• (Syntax for Designated and Convenience Initializers)

ํด๋ž˜์Šค์˜ ์ง€์ • ์ดˆ๊ธฐ์ž์˜ ๋ฌธ๋ฒ•์€ ๊ฐ’ ํƒ€์ž… ์ดˆ๊ธฐ์ž์™€ ๊ฐ™๋‹ค.

init(parameters) {
    statements
}

ํŽธ์˜ ์ƒ์„ฑ์ž๋Š” ๊ธฐ๋ณธ ์ƒ์„ฑ์ž์™€ ๋ฌธ๋ฒ•์ด ๊ฐ™์ง€๋งŒ init ์•ž์— convenience ํ‚ค์›Œ๋“œ๋ฅผ ๋ถ™์—ฌ ์ค€๋‹ค.

convenience init(parameters) {
    statements
}

ํด๋ž˜์Šค ํƒ€์ž…์„ ์œ„ํ•œ ์ด๋‹ˆ์…œ๋ผ์ด์ € ์œ„์ž„ (Initializer Delegation for Class Types)

์ง€์ • ์ดˆ๊ธฐ์ž์™€ ํŽธ๋ฆฌํ•œ ์ดˆ๊ธฐ์ž ์‚ฌ์ด์˜ ๊ด€๊ณ„๋ฅผ ๋‹จ์ˆœํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด Swift๋Š” ์ด๋‹ˆ์…œ๋ผ์ด์ €๋Š” ์œ„์ž„ํ•˜๋Š” ํ˜ธ์ถœ์„ ์œ„ํ•ด ๋‹ค์Œ 3๊ฐ€์ง€ ๊ทœ์น™์„ ๋”ฐ๋ฅธ๋‹ค.

  • ๊ทœ์น™ 1 ์ง€์ • ์ดˆ๊ธฐ์ž๋Š” ๋ฐ˜๋“œ์‹œ ์ง๊ณ„ superclass์˜ ์ง€์ • ์ƒ์„ฑ์ž๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค.
  • ๊ทœ์น™ 2 ํŽธ์˜ ์ƒ์„ฑ์ž๋Š” ๋ฐ˜๋“œ์‹œ ๊ฐ™์€ ํด๋ž˜์Šค์˜ ๋‹ค๋ฅธ ์ƒ์„ฑ์ž๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค.
  • ๊ทœ์น™ 3 ํŽธ์˜ ์ƒ์„ฑ์ž๋Š” ๊ถ๊ทน์ ์œผ๋กœ ์ง€์ •์ƒ์„ฑ์ž๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค.

๊ธฐ์–ตํ•˜๊ธฐ ์‰ฝ๊ฒŒ ์š”์•ฝํ•˜์ž๋ฉด

  • ์ง€์ • ์ดˆ๊ธฐ์ž๋Š” ๋ฐ˜๋“œ์‹œ ์œ„์ž„์„ superclass๋กœ ํ•ด์•ผํ•˜๊ณ 
  • ํŽธ๋ฆฌํ•œ ์ดˆ๊ธฐ์ž๋Š” ๋ฐ˜๋“œ์‹œ ์œ„์ž„์„ ๊ฐ™์€ ๋ ˆ๋ฒจ์—์„œ ํ•ด์•ผํ•œ๋‹ค.

๊ทธ๋ฆผ์„ ๋ณด๋ฉด Subclass์˜ ํŽธ๋ฆฌํ•œ ์ดˆ๊ธฐ์ž๋Š” ๊ฐ™์€ ๋ ˆ๋ฒจ์—์„œ ๋‹ค๋ฅธ ์ง€์ • ์ƒ์„ฑ์ž๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ์ง€์ • ์ƒ์„ฑ์ž๋Š” ์ดˆ๊ธฐํ™”๋ฅผ ์ƒ์œ„ ํด๋ž˜์Šค์—๊ฒŒ ์œ„์ž„ํ•ด ์ƒ์œ„ ํด๋ž˜์Šค์˜ ์ง€์ • ์ƒ์„ฑ์ž๊ฐ€ ํ˜ธ์ถœ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

NOTEโ—๏ธ
์ƒ์„ฑ์ž ํ˜ธ์ถœ์˜ ํ˜•ํƒœ๊ฐ€ ๋ฐ˜๋“œ์‹œ ์œ„ ์ฒ˜๋Ÿผ ๋˜์•ผ ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. ์œ„์—์„œ ์–ธ๊ธ‰๋งŒ ๊ทœ์น™๋งŒ ์ง€์ผœ์ง€๋ฉด ์ƒ๊ด€ ์—†๋‹ค.

2๋‹จ๊ณ„ ์ดˆ๊ธฐํ™” (Two-Phase Initialization)

Swift์—์„œ ํด๋ž˜์Šค ์ดˆ๊ธฐํ™”๋Š” 2๋‹จ๊ณ„๋กœ ์ง„ํ–‰๋œ๋‹ค. ์ฒซ๋ฒˆ์งธ ๋‹จ๊ณ„์—์„œ๋Š” ๊ฐ ์ €์žฅ๋œ ํ”„๋กœํผํ‹ฐ๋Š” ์ดˆ๊ธฐ๊ฐ’์œผ๋กœ ์ดˆ๊ธฐํ™” ๋œ๋‹ค. ๋ชจ๋“  ์ €์žฅ๋œ ํ”„๋กœํผํ‹ฐ์˜ ์ƒํƒœ๊ฐ€ ๊ฒฐ์ •๋˜๋ฉด ๋‘๋ฒˆ์งธ ๋‹จ๊ณ„๊ฐ€ ์‹œ์ž‘๋œ๋‹ค. ๋‘๋ฒˆ์งธ ๋‹จ๊ณ„์—์„œ๋Š” ์ƒˆ๋กœ์šด ์ธ์Šคํ„ด์Šค์˜ ์‚ฌ์šฉ์ด ์ค€๋น„๋๋‹ค๊ณ  ์•Œ๋ ค์ฃผ๊ธฐ ์ „์— ์ €์žฅ๋œ ํ”„๋กœํผํ‹ฐ๋ฅผ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•˜๋Š” ๋‹จ๊ณ„์ด๋‹ค.

Swift์˜ ์ปดํŒŒ์ผ๋Ÿฌ๋Š” 2๋‹จ๊ณ„ ์ดˆ๊ธฐํ™”๊ฐ€ ์—๋Ÿฌ์—†์ด ๋๋‚˜๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด 4๋‹จ๊ณ„ ์•ˆ์ „ ํ™•์ธ(safety-check)์„ ํ•œ๋‹ค.

  • ์•ˆ์ „ ํ™•์ธ 1๋‹จ๊ณ„ ์ง€์ • ์ƒ์„ฑ์ž๋Š” ํด๋ž˜์Šค ์•ˆ์—์„œ ์ดˆ๊ธฐํ™”๋ฅผ superclass์˜ ์ƒ์„ฑ์ž์—๊ฒŒ ์œ„์ž„ํ•˜๊ธฐ ์ „์— ๋ชจ๋“  ํ”„๋กœํผํ‹ฐ๋ฅผ ์ดˆ๊ธฐํ™” ํ•ด์•ผํ•œ๋‹ค. ์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ๊ฒƒ ์ฒ˜๋Ÿผ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ๊ฐ์ฒด๋Š” ๋ชจ๋“  ์ €์žฅ๋œ ํ”„๋กœํผํ‹ฐ๊ฐ€ ์ดˆ๊ธฐ ์ƒํƒœ๋ฅผ ๊ฐ–์–ด์•ผ๋งŒ ์™„์ „ํžˆ ์ดˆ๊ธฐํ™” ๋œ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ด ๊ทœ์น™์„ ๋งŒ์กฑ์‹œํ‚ค๊ธฐ ์œ„ํ•ด ์ง€์ • ์ƒ์„ฑ์ž๋Š” ๋ฐ˜๋“œ์‹œ ๋‹ค๋ฅธ ์ƒ์„ฑ์ž๋กœ ๋„˜๊ธฐ๊ธฐ ์ „์— ์†Œ์œ ํ•˜๊ณ ์žˆ๋Š” ๋ชจ๋“  ํ”„๋กœํผํ‹ฐ๋ฅผ ์ดˆ๊ธฐํ™” ํ•ด์•ผ ํ•œ๋‹ค.
  • ์•ˆ์ „ ํ™•์ธ 2๋‹จ๊ณ„ ์ง€์ • ์ƒ์„ฑ์ž๋Š” ๋ฐ˜๋“œ์‹œ ์ƒ์†๋œ ๊ฐ’์„ ํ• ๋‹นํ•˜๊ธฐ ์ „์— superclass์˜ ์ƒ์„ฑ์ž๋กœ ์œ„์ž„์„ ๋„˜๊ฒจ์•ผ ํ•œ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์ƒ์†๋œ ๊ฐ’์ด superclass์ด ์ƒ์„ฑ์ž์— ์˜ํ•ด ๋ฎ์–ด ์“ฐ์—ฌ์ง€๊ฒŒ ๋œ๋‹ค.
  • ์•ˆ์ „ ํ™•์ธ 3๋‹จ๊ณ„ ํŽธ์˜ ์ƒ์„ฑ์ž๋Š” ๋ฐ˜๋“œ์‹œ ์–ด๋–ค ํ”„๋กœํผํ‹ฐ๋ฅผ ํ• ๋‹นํ•˜๊ธฐ ์ „์— ๋‹ค๋ฅธ ์ƒ์„ฑ์ž๋กœ ์œ„์ž„์„ ๋„˜๊ฒจ์•ผ ํ•œ๋‹ค. ๋งŒ์•ฝ ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ํŽธ์˜ ์ƒ์„ฑ์ž์— ์˜ํ•ด ํ• ๋‹น๋œ ๊ฐ’์„ ๋‹ค๋ฅธ ํด๋ž˜์Šค์˜ ์ง€์ • ์ƒ์„ฑ์ž์— ์˜ํ•ด ๋ฎ์–ด ์“ฐ์—ฌ์ง€๊ฒŒ ๋œ๋‹ค.
  • ์•ˆ์ „ ํ™•์ธ 4๋‹จ๊ณ„ ์ด๋‹ˆ์…œ๋ผ์ด์ €๋Š” ์ดˆ๊ธฐํ™”์˜ 1๋‹จ๊ณ„๊ฐ€ ๋๋‚˜๊ธฐ ์ „์—๋Š” self์˜ ๊ฐ’์„ ์ฐธ์กฐํ•˜๊ฑฐ๋‚˜ ์–ด๋–ค ์ธ์Šคํ„ด์Šค ํ”„๋กœํผํ‹ฐ, ๋ฉ”์†Œ๋“œ ๋“ฑ์„ ํ˜ธ์ถœํ•˜๊ฑฐ๋‚˜ ์ฝ์„ ์ˆ˜ ์—†๋‹ค.

์ด๋‹ˆ์…œ๋ผ์ด์ €์˜ ์ƒ์†๊ณผ ์˜ค๋ฒ„๋ผ์ด๋”ฉ (Initializer Inheritance and Overriding)

Swift์—์„œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ subclass์—์„œ superclass์˜ ์ด๋‹ˆ์…œ๋ผ์ด์ €๋ฅผ ์ƒ์†ํ•˜์ง€ ์•Š๋Š”๋‹ค. ์ด์œ ๋Š” superclass์˜ ์ด๋‹ˆ์…œ๋ผ์ด์ €๊ฐ€ ๋ฌด๋ถ„๋ณ„ํ•˜๊ฒŒ ์ƒ์†๋ผ ๋ณต์žกํ•˜๊ฒŒ ๋ผ subclass์—์„œ ์ด๊ฒƒ๋“ค์ด ์ž˜๋ชป ์ดˆ๊ธฐํ™” ๋˜๋Š” ๊ฒƒ์„ ๋ง‰๊ธฐ ์œ„ํ•จ์ด๋‹ค.

๋งŒ์•ฝ ํด๋ž˜์Šค์—์„œ ๋ชจ๋“  ํ”„๋กœํผํ‹ฐ์˜ ์ดˆ๊ธฐ ๊ฐ’์ด ์ง€์ •๋ผ ์žˆ๊ณ  ์•„๋ฌด๋Ÿฐ ์ปค์Šคํ…€ ์ดˆ๊ธฐ์ž๋ฅผ ์„ ์–ธํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด ๊ธฐ๋ณธ ์ดˆ๊ธฐ์ž init()์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.superclass์˜ ์ดˆ๊ธฐ์ž๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œ ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” subclass์—์„œ ๊ทธ ์ดˆ๊ธฐ์ž์— override ํ‚ค์›Œ๋“œ๋ฅผ ๋ถ™์ด๊ณ  ์žฌ์ •์˜ ํ•œ๋‹ค.

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

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

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

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

์ž๋™ ์ƒ์„ฑ์ž ์ธ์Šคํ„ด์Šค (Automatic Initializer Inheritance)

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

ํŽธ์˜ ์ƒ์„ฑ์ž convenience init()์—์„œ ์ง€์ •์ƒ์„ฑ์ž init(name: String)์ด ํ˜ธ์ถœ๋˜๋Š” ํ˜•ํƒœ์ด๋‹ค.

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)
    }
}

์ˆ˜ํผํด๋ž˜์Šค์˜ init(name: name) ์ƒ์„ฑ์ž๋ฅผ ์ƒ์†๋ฐ›์•„ ์ง€์ •์ƒ์„ฑ์ž๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๊ทธ ์ง€์ •์ƒ์„ฑ์ž๋ฅผ ํŽธ์˜ ์ƒ์„ฑ์ž convenience init(name: String)์—์„œ ์˜ค๋ฒ„๋ผ์ด๋”ฉํ•ด ์‚ฌ์šฉํ•œ๋‹ค.

์ด๋ ‡๊ฒŒ ์ƒ์„ฑํ•œ RecipeIngredient ํด๋ž˜์Šค๋Š” ๋‹ค์Œ 3๊ฐ€์ง€ ํ˜•ํƒœ์˜ ์ดˆ๊ธฐ์ž๋ฅผ ์ด์šฉํ•ด ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

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

ShoppingListItem๋Š” purchased๋ผ๋Š” bool ํ”„๋กœํผํ‹ฐ์™€ description์ด๋ผ๋Š” ๊ณ„์‚ฐ๋œ ํ”„๋กœํผํ‹ฐ 2๊ฐ€์ง€๋ฅผ ์ƒˆ๋กœ ์ƒ์„ฑํ•œ๋‹ค.

class ShoppingListItem: RecipeIngredient {
    var purchased = false
    var description: String {
        var output = "\(quantity) x \(name)"
        output += purchased ? " โœ”" : " โœ˜"
        return output
    }
}

์ด์ œ ์ด ๋ชจ๋“  3๊ฐœ์˜ ์ดˆ๊ธฐ์ž๋ฅผ ์ด์šฉํ•ด ShoppingListItem ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

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 โœ˜

์‹คํŒจ ๊ฐ€๋Šฅ ์ƒ์„ฑ์ž (Failable Initializers)

์ดˆ๊ธฐํ™” ๊ณผ์ • ์ค‘์— ์‹คํŒจํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋Š” ์ƒ์„ฑ์ž๋ฅผ init๋’ค์— ๋ฌผ์Œํ‘œ(?)๋ฅผ ์‚ฌ์šฉํ•ด ์‹คํŒจ๊ฐ€ ๊ฐ€๋Šฅํ•œ ์ƒ์„ฑ์ž๋ผ๊ณ  ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ๋‹ค.

NOTEโ—๏ธ
์ƒ์„ฑ์ž๋Š” ์ด๋ฆ„์ด ๋”ฐ๋กœ ์žˆ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๊ตฌ๋ถ„ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์‹คํŒจ ๊ฐ€๋Šฅํ•œ ์ดˆ๊ธฐ์ž์™€ ์‹คํŒจ ๋ถˆ๊ฐ€๋Šฅํ•œ ์ดˆ๊ธฐ์ž๋ฅผ ๊ฐ™์€ ํŒŒ๋ผ๋ฏธํ„ฐ ํƒ€์ž…๊ณผ ์ด๋ฆ„์œผ๋กœ ๋™์‹œ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค. ์‹คํŒจ ๊ฐ€๋Šฅํ•œ ์ดˆ๊ธฐ์ž๋Š” ๋ฐ˜ํ™˜๊ฐ’์œผ๋กœ ์˜ต์…”๋„ ๊ฐ’์„ ์ƒ์„ฑํ•œ๋‹ค. ์ดˆ๊ธฐํ™”์— ์‹คํŒจํ•˜๋Š” ๋ถ€๋ถ„์—์„œ nil์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด ์ดˆ๊ธฐํ™”๊ฐ€ ์‹คํŒจํ–ˆ๋‹ค๋Š” ๊ฒƒ์„ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

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

์—ด๊ฑฐํ˜•์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์‹คํŒจ ๊ฐ€๋Šฅํ•œ ์ƒ์„ฑ์ž (Failable Initializers for Enumerations)

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
        }
    }
}

ํ•„์ˆ˜ ์ƒ์„ฑ์ž (Required Initializers)

๋ชจ๋“  ์„œ๋ธŒํด๋ž˜์Šค์—์„œ ๋ฐ˜๋“œ์‹œ ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋Š” ์ดˆ๊ธฐ์ž์—๋Š” ์•„๋ž˜ ์˜ˆ์ œ์™€ ๊ฐ™์ด required ํ‚ค์›Œ๋“œ๋ฅผ ๋ถ™์—ฌ ์ค€๋‹ค.

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

NOTEโ—๏ธ
ํ•„์ˆ˜์ดˆ๊ธฐ์ž ํ‘œ์‹œ๋ฅผ ํ•ด๋„ ๊ผญ ๊ตฌํ˜„์„ ํ•  ํ•„์š”๋Š” ์—†๋‹ค.

ํด๋กœ์ €๋‚˜ ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด ๊ธฐ๋ณธ ํ”„๋กœํผํ‹ฐ ๊ฐ’์„ ์„ค์ •ํ•˜๊ธฐ (Setting a Default Property Value with a Closure or Function)

๊ธฐ๋ณธ ๊ฐ’ ์„ค์ •์ด ๋‹จ์ˆœํžˆ ๊ฐ’์„ ํ• ๋‹นํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๋‹ค์†Œ ๋ณต์žกํ•œ ๊ณ„์‚ฐ์„ ํ•„์š”ํ•˜๋‹ค๋ฉด ํด๋กœ์ €๋‚˜ ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด ๊ฐ’์„ ์ดˆ๊ธฐํ™” ํ•˜๋Š”๋ฐ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

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๋ฅผ ๊ธฐ๋ณธ ๊ฐ’์œผ๋กœ ๊ฐ–๊ฒŒ ๋œ๋‹ค.

NOTEโ—๏ธ
ํด๋กœ์ €๋ฅผ ์ดˆ๊ธฐ์ž์—์„œ ์‚ฌ์šฉํ•˜๋ฉด ํด๋กœ์ € ์•ˆ์— self๋‚˜ ๋‹ค๋ฅธ ํ”„๋กœํผํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ ์ด์œ ๋Š” ํด๋กœ์ €๊ฐ€ ์‹คํ–‰๋  ์‹œ์ ์— ๋‹ค๋ฅธ ํ”„๋กœํผํ‹ฐ๋Š” ์ดˆ๊ธฐํ™”๊ฐ€ ๋‹ค ๋๋‚œ ๊ฒƒ์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

'๐Ÿฆ… Swift' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

Inheritance  (0) 2022.07.05
Subscripts  (0) 2022.07.04
Methods  (0) 2022.07.04
Properties  (0) 2022.07.04
Structures and Classes  (0) 2022.06.22