본문 바로가기
모바일앱/Swift

생성자 이해하기, 2-phase Initialization, Convenience Initializer

by GeekCode 2021. 10. 20.
반응형

Initializer (생성자)

 

앞선 강의에서 Inheritance(상속)에 대해서 공부했다.

상속받은 클래스들을 생성할때 기본 생성자를 가지고 만드는데 부모자식간의 모양이 비슷한 것을 알 수 있다.

하지만 자식 클래스는 부모와 다르게 만들 수도 있다.

import UIKit

// 처음 코드
struct Grade {
    var letter: Character
    var points: Double
    var credits: Double
}

class Person {
    var firstName: String
    var lastName: String

    init(firstName: String, lastName: String) {
        self.firstName = firstName
        self.lastName = lastName
    }

    func printMyName() {
        print("My name is \(firstName) \(lastName)")
    }
}

class Student: Person {
    var grades: [Grade] = []
}

// 학생인데 운동선수
class StudentAthlete: Student {
    var minimumTrainingTime: Int = 2
    var trainedTime: Int = 0
    var sports: [String] //운동선수라 새로운 내용 추가 하고 싶을때
    //클래스에서는 stored property를 추가하려면 initialize를 해야한다.
    
    init(firstName: String, lastName: String, sports: [String]) {
        // Phase 1
        self.sports = sports
        //부모클래스에 있는 이니셜라이즈를 가져오는 것
        super.init(firstName: firstName, lastName: lastName)
        
        //  Phase 2
        // 1을 세팅마치고 나서 하지않으면 에러메세지가 뜬다.
        self.train()
    }

    
    func train() {
        trainedTime += 1
    }
}

// 운동선인데 축구선수
class FootballPlayer: StudentAthlete {
    var footballTeam = "FC Swift"

    override func train() {
        trainedTime += 2
    }
}

let student1 = Student(firstName: "Jason", lastName: "Lee")
let student2 = StudentAthlete(firstName: "Jay", lastName: "Lee", sports: ["Football"])

 

2-phase Initialization (생성시 2가지 단계 )

자식클래스에서 먼저 Stored Property 를 세팅하고 

부모 클래스의 프로퍼티를 세팅해야하는 규칙 

 

 

 

Phase 1. 

모든 Stored Property 는 모두 이니셜라이즈 되어야한다.

 

자식클래스 이니셜라이즈 먼저 챙기고 부모클래스 이니셜라이즈 챙기기

StudentAthlete가 갖고 있는 스포츠라는 프로퍼티를 먼저 세팅해주고 부모 클래스 세팅해주기 

 

Phase 2.

부모 클래스까지 세팅후에 프로퍼티와 메소드를 사용가능하게 된다.

이러한 규칙이 없다면 이니셜라이저에서 프로퍼티가 세팅도 안된상태에서 인스턴스 메소들을 호출하게 되고 

우리가 원하는 동작을 하지않고 버그가 생길 것이다.

그래서 이런 강력한 룰이 생긴 것이다. 

 

 

 

Convenience Initializer (부 이니셜라이저) ; CI , Conv init

점점 길어지는 경우가 있다. 

그럴때 CI를 사용하면

간략하게 만들어줄수 있다.

 

designated Initializer (주 이니셜라이저)

- DI는 자신의 부모의 DI를 호출해야 함.

- CI는 같은 클래스의 이니셜라이저를 꼭 하나 호출해야함.

- CI는 궁극적으로는 DI를 호출해야함

 

struct Grade {
    var letter: Character
    var points: Double
    var credits: Double
}

class Person {
    var firstName: String
    var lastName: String

    init(firstName: String, lastName: String) {
        self.firstName = firstName
        self.lastName = lastName
    }

    func printMyName() {
        print("My name is \(firstName) \(lastName)")
    }
}

class Student: Person {
    var grades: [Grade] = []
    
    
    // designated Initializer
    override init(firstName: String, lastName: String) {
        super.init(firstName: firstName, lastName: lastName)
    }
    // Covenience Initializer
    convenience init(student: Student) {
        self.init(firstName: student.firstName, lastName: student.lastName)
    }
    
    
}

// 학생인데 운동선수
class StudentAthlete: Student {
    var minimumTrainingTime: Int = 2
    var trainedTime: Int = 0
    var sports: [String]
    
    init(firstName: String, lastName: String, sports: [String]) {
        // Phase 1
        self.sports = sports
        super.init(firstName: firstName, lastName: lastName)
        
        // Phase 2
        self.train()
    }
    
    
    convenience init(name: String) {
        self.init(firstName: name, lastName: "", sports: [])
    }
    
        
    func train() {
        trainedTime += 1
    }
}

// 운동선인데 축구선수
class FootballPlayer: StudentAthlete {
    var footballTeam = "FC Swift"

    override func train() {
        trainedTime += 2
    }
}

let student1 = Student(firstName: "Jason", lastName: "Lee")
let student1_1 = Student(student: student1)
let student2 = StudentAthlete(firstName: "Jay", lastName: "Lee", sports: ["Football"])
let student3 = StudentAthlete(name: "Mike")

클래스 안에서는 여러가지의 initializer를 만들수있는데 "주 와 부" 두가지가 있다.

부 이니셜라이저들은 다른 이니셜라이저들을 호출하게 되어있다.

Conv init들은 다른 컨비니언스 이니셜라이저를 호출하는데 최종적으로는 DI를 궁극으로는 불러야한다.

 

반응형

'모바일앱 > Swift' 카테고리의 다른 글

Day04 For_Loops  (0) 2021.11.29
Day03: enum  (0) 2021.11.29
Day02 : For-each(자료 보강 필요)  (0) 2021.11.28
Day01 : Conditional Statements_If  (0) 2021.11.26
클래스상속은 언제 하면 좋을까?  (0) 2021.10.19
상속 개념을 코드로 익히기  (0) 2021.10.18
클래스, 언제 클래스? 언제 스트럭트?  (0) 2021.10.16
메소드 개념 ( + extension)  (0) 2021.10.14