Swift ํด๋ž˜์Šค ์ƒ์†๊ณผ ์ดˆ๊ธฐํ™”
iOS ๐Ÿ”ฅ/Swift

Swift ํด๋ž˜์Šค ์ƒ์†๊ณผ ์ดˆ๊ธฐํ™”

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

์ง€์ • ์ดˆ๊ธฐ์ž์™€ ํŽธ๋ฆฌํ•œ ์ดˆ๊ธฐ์ž

์ง€์ •์ดˆ๊ธฐ์ž๋Š” primary ์ดˆ๊ธฐ์ž์ด๋ฉฐ, ๋ชจ๋“  ํ”„๋กœํผํ‹ฐ๋ฅผ ์ดˆ๊ธฐํ™” ํ•ฉ๋‹ˆ๋‹ค.
ํด๋ž˜์Šค ํƒ€์ž…์€ ๋ฐ˜๋“œ์‹œ ํ•œ ๊ฐœ ์ด์ƒ์˜ ์ง€์ • ์ดˆ๊ธฐ์ž๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํŽธ๋ฆฌํ•œ ์ดˆ๊ธฐ์ž๋Š” ์ตœ์†Œํ•œ์˜ ์ž…๋ ฅ์œผ๋กœ ์ดˆ๊ธฐํ™”๋ฅผ ํ•˜๋ฉฐ, ๋‚ด๋ถ€์—์„œ ๋ฐ˜๋“œ์‹œ ์ง€์ • ์ดˆ๊ธฐ์ž๊ฐ€ ํ˜ธ์ถœ๋ผ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

// ์ง€์ • ์ดˆ๊ธฐ์ž
init(parameters) {
    statements
}
// ํŽธ๋ฆฌํ•œ ์ดˆ๊ธฐ์ž
convenience init(parameters) {
    statements
}

ํด๋ž˜์Šค ํƒ€์ž…์„ ์œ„ํ•œ ์ด๋‹ˆ์…œ๋ผ์ด์ € ์œ„์ž„

3๊ฐ€์ง€ ๊ทœ์น™์„ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค.

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

๊ทœ์น™2. ํŽธ๋ฆฌํ•œ ์ดˆ๊ธฐ์ž๋Š” ๋ฐ˜๋“œ์‹œ ๊ฐ™์€ ํด๋ž˜์Šค์˜ ๋‹ค๋ฅธ ์ดˆ๊ธฐ์ž๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ทœ์น™3. ํŽธ๋ฆฌํ•œ ์ดˆ๊ธฐ์ž๋Š” ๊ถ๊ทน์ ์œผ๋กœ ์ง€์ •์ดˆ๊ธฐ์ž๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

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

์ฒซ ๋ฒˆ์งธ ๋‹จ๊ณ„์—์„œ๋Š” ๊ฐ ์ €์žฅ๋œ ํ”„๋กœํผํ‹ฐ๋ฅผ ์ดˆ๊ธฐ๊ฐ’์œผ๋กœ ์ดˆ๊ธฐํ™” ํ•ฉ๋‹ˆ๋‹ค.
๋ชจ๋“  ์ €์žฅ๋œ ํ”„๋กœํผํ‹ฐ์˜ ์ƒํƒœ๊ฐ€ ๊ฒฐ์ •๋˜๋ฉด, ๋‘๋ฒˆ์งธ ๋‹จ๊ณ„๊ฐ€ ์‹œ์ž‘๋˜๋Š”๋ฐ, ์ด ๋‹จ๊ณ„์—์„œ ์ €์žฅ๋œ ํ”„๋กœํผํ‹ฐ๋ฅผ ์ปค์Šคํ„ฐ๋งˆ์ด์ง• ํ•ฉ๋‹ˆ๋‹ค.

Safety Check 4๋‹จ๊ณ„

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

2. ์ง€์ • ์ดˆ๊ธฐ์ž๋Š” ์ƒ์†๋œ ๊ฐ’์„ ํ• ๋‹นํ•˜๊ธฐ ์ „์— super class์˜ ์ดˆ๊ธฐ์ž๋กœ ์œ„์ž„์„ ๋„˜๊ฒจ์•ผ ํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์ƒ์†๋œ ๊ฐ’์ด superclass ์ดˆ๊ธฐ์ž์— ๋ฎ์–ด ์“ฐ์—ฌ์ง€๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

3. ํŽธ๋ฆฌํ•œ ์ดˆ๊ธฐ์ž๋Š” ์–ด๋–ค ํ”„๋กœํผํ‹ฐ๋ฅผ ํ• ๋‹นํ•˜๊ธฐ ์ „์— ๋ฐ˜๋“œ์‹œ ๋‹ค๋ฅธ ์ดˆ๊ธฐ์ž๋กœ ์œ„์ž„์„ ๋„˜๊ฒจ์•ผ ํ•ฉ๋‹ˆ๋‹ค.
๋งŒ์•ฝ ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด, ํŽธ๋ฆฌํ•œ ์ดˆ๊ธฐ์ž์— ์˜ํ•ด ํ• ๋‹น๋œ ๊ฐ’์ด ๋‹ค๋ฅธ ํด๋ž˜์Šค์˜ ์ง€์ • ์ดˆ๊ธฐ์ž์— ์˜ํ•ด ๋ฎ์–ด ์“ฐ์—ฌ์ง€๊ฒŒ ๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

4. ์ด๋‹ˆ์…œ๋ผ์ด์ €๋Š” ์ดˆ๊ธฐํ™”์˜ 1๋‹จ๊ณ„๊ฐ€ ๋๋‚˜๊ธฐ ์ „์—๋Š” self์˜ ๊ฐ’์„ ์ฐธ์กฐํ•˜๊ฑฐ๋‚˜ ์–ด๋–ค ์ธ์Šคํ„ด์Šค ํ”„๋กœํผํ‹ฐ, ๋ฉ”์†Œ๋“œ ๋“ฑ์„ ํ˜ธ์ถœํ•˜๊ฑฐ๋‚˜ ์ฝ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์‹คํŒจ ๊ฐ€๋Šฅํ•œ ์ดˆ๊ธฐ์ž

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

struct Animal {
    let species: String
    init?(species: String) {
        if species.isEmpty { return nil }
        self.species = species
    }
}
let anonymousCreature = Animal(species: "")
// anonymousCreature is of type Animal?, not Animal
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
        }
    }
}
TemperatureUnit(symbol: "X") // ์‹คํŒจ

๊ทธ ์™ธ์— ์ˆ˜ํผํด๋ž˜์Šค์˜ ์‹คํŒจ๊ฐ€๋Šฅํ•œ ์ดˆ๊ธฐ์ž๋ฅผ ์„œ๋ธŒํด๋ž˜์Šค์—์„œ ์‹คํŒจ๋ถˆ๊ฐ€๋Šฅํ•œ ์ดˆ๊ธฐ์ž๋กœ ์˜ค๋ฒ„๋ผ์ด๋”ฉ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฐฉ๋ฒ•์„ ์ด์šฉํ•ด ์‹คํŒจ๋ถˆ๊ฐ€๋Šฅํ•œ ์ดˆ๊ธฐ์ž๋ฅผ ์ƒ์„ฑ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. (์„œ๋ธŒ ํด๋ž˜์Šค์—์„œ ์ƒ์œ„ ํด๋ž˜์Šค์˜ ์‹คํŒจ์กฐ๊ฑด์„ ์ฒ˜๋ฆฌํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.)

init? ์ดˆ๊ธฐ์ž๋ฅผ init! ์ดˆ๊ธฐ์ž๋กœ ์˜ค๋ฒ„๋ผ์ด๋”ฉํ•˜๊ฑฐ๋‚˜ ์œ„์ž„ํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ.

ํ•„์ˆ˜ ์ดˆ๊ธฐ์ž

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

class SomeClass {
    required init() {
        // initializer implementation goes here
    }
}
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
    }()
}

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