본문 바로가기
🍎iOS프로그래밍/오늘의 공부

Swift의 생성자 init()-Failable/Default/ Disignated/ iOS프로그래밍

by 둥둥동동# 2021. 10. 2.
728x90

생성자 init()

 

생성자 init()

default initializer

designated initializer

응용

 

init() 생성자란?

 

클래스에 선언된 모든 프로퍼티는 초기화 되어야만 합니다

이 때 초기화하는 방법 중 하나로 init()생성자를 호출하는 방법이 있습니다

인스턴스를 생성하면서 init()생성자가 자동으로 호출되어 프로퍼티가 초기화 됩니다

 

 

Default initializer

 

사실 우리는 init()생성자를 명시하지 않았어도 항상 init()생성자를 호출하고 있었습니다

아래의 예시를 보겠습니다

class human{
    var age: Int = 16
    var kg_w: Int = 20
    var job:String = "jobless"
 
    func Method1(){ //인스턴스 메서드 선언방식
        print("메서드1번입니다")
    }
    
}
var Kim:human = human()
Kim.Method1()
cs

 

human클래스는 init()생성자를 작성하지 않았습니다

인스턴스 Kim을 선언하고 human()을 실행합니다 이 때 human()를 사용하는 이유가 default initailizer를 이용하기 때문입니다

아래의 Designated initailizer와 비교해 보겠습니다

 

 

Designated initializer

 

Disigneated Initializer는 클래스의 모든 프로퍼티를 초기화하는 생성자를 뜻합니다

class human{
    var age: Int = 16
    var kg_w: Double = 20.5
    var job:String = "jobless"
 
    func Method1(){ //인스턴스 메서드 선언방식
        print("메서드1번입니다")
    }
    
    init(agei:Int, kg_wi:Double, jobi:String){
        age = agei
        kg_w = kg_wi
        job = jobi
    }
    
}
var Kim:human = human(agei:2, kg_wi:10.5, jobi:"actor")
print("\(Kim.age) + \(Kim.kg_w) + \(Kim.job)")
//2 + 10.5 + actor
cs

디폴트init()과 차이점은 클래스에 init()생성자를 정의하고 인스턴스 생성시 init()에서 정의한 매개변수를 넣는다는 것입니다

 

인스턴스를 생성할 때마다 생성자를 통해 프로퍼티를 초기화 하므로 상단의 프로퍼티는 아래와 같이 생략가능합니다

class human{
    var age: Int
    var kg_w: Double
    var job:String
 
    func Method1(){ //인스턴스 메서드 선언방식
        print("메서드1번입니다")
    }
    
    init(agei:Int, kg_wi:Double, jobi:String){
        age = agei
        kg_w = kg_wi
        job = jobi
    }
    
}
var Kim:human = human(agei:2, kg_wi:10.5, jobi:"actor")
print("\(Kim.age) + \(Kim.kg_w) + \(Kim.job)")
//2 + 10.5 + actor
cs

상단의 프로퍼티 초기화를 생략해도 정상적으로 동작합니다

 

 

 

생성자의 오버로딩

 

Swift는 오버로딩을 지원하기 때문에 init()생성자를 여러개 만들어둘 수 있습니다

class human{
    var age: Int
    var kg_w: Double
    var job:String
 
    func Method1(){ //인스턴스 메서드 선언방식
        print("메서드1번입니다")
    }
    
    init(agei:Int, kg_wi:Double, jobi:String){
        age = agei
        kg_w = kg_wi
        job = jobi
    }
    init(age:Int, kg_w:Double){
       age = age
       kg_w = kg_w
    }
}
var Kim:human = human(agei:2, kg_wi:10.5, jobi:"actor")
print("\(Kim.age) + \(Kim.kg_w) + \(Kim.job)")
cs

상단의 생성자와 하단의 생성자는 서로다른 이름의 매개변수를 받기 때문에 서로다른 생성자로 취급됩니다

이 코드는 정상동작할것 같지만 두가지 문제점이 있습니다

첫번째로 init()생성자의 매개변수age와 human클래스의 프로퍼티 age가 서로 중복되어 구별을 할 수 없는 상황입니다

이때는 init()생성자에서 self키워드를 통해 클래스의 age임을 명확히 표기해야 합니다

    init(age:Int, kg_w:Double){
        self.age = age
        self.kg_w = kg_w
    }
cs

 

 

두번째 문제점은 프로퍼티 job이 초기화되지 않은 것입니다

상단의 생성자에서는 job을 초기화 하지만 하단 생성자에서는 job을 초기화하지 않기 때문입니다

때문에 job을 선언과 동시에 초기화를 하거나 모든 init()생성자에서 job을 초기화 시켜주어야 합니다

class human{
    var age: Int
    var kg_w: Double
    var job:String = "jobless"
 
    func Method1(){ //인스턴스 메서드 선언방식
        print("메서드1번입니다")
    }
    
    init(agei:Int, kg_wi:Double, jobi:String){
        age = agei
        kg_w = kg_wi
        job = jobi
    }
    init(age:Int, kg_w:Double){
        self.age = age
        self.kg_w = kg_w
    }
}
var Kim:human = human(agei:2, kg_wi:10.5, jobi:"actor")
print("\(Kim.age) + \(Kim.kg_w) + \(Kim.job)")
cs

 

 

Failable initailizer

 

init()생성자에 잘못된 값을 넣게 되면 치명적인 오류가 발생할 수 있습니다

이런경우 nil을 리턴하는 failable initializer로 오류를 막을 수 있습니다

아래와 같이 정의할 수 있습니다

class human{
    var age: Int
    var kg_w: Double
    var job:String = "jobless"
 
    func out(){ //인스턴스 메서드 선언방식
        print("나이:\(age), 무게:\(kg_w), 직업:\(job)")
    }
    
    init?(age:Int, kg_w:Double, _ job:String){
        if(age <= 0 || kg_w <= 0){
            return nil
        }else{
            self.age = age
            self.kg_w = kg_w
        }
        self.job = job
    }
}
var Kim:human = human(age:2, kg_w:10.5"actor")!
print("\(Kim.age) + \(Kim.kg_w) + \(Kim.job)")
cs

init?()형식으로 사용하고 if문에서 0이하 값이 들어오면 nil을 리턴합니다

 

init?() 생성자는 옵셔널타입을 리턴하므로 값을 활용하기 위해서는 언래핑과정이 필요합니다

언래핑 과정에는 크게 2가지 방식이 있습니다

if문을 통한 옵셔널 바인딩, !키워드를 이용한 강제 언래핑이 있습니다

nil값이 들어있을 때 강제언래핑을하면 crash가 발생하기 때문에 충돌위험이 있는 강제 언래핑은 권장하는 방법이 아닙니다

 

옵셔널바인딩 방식

var Kim: human? = human(age:2, weight:17.5"actor"//옵셔널타입으로 선언
if let Kim1 = Kim{ //옵셔널바인딩으로 언래핑, nil일 경우 무시
    Kim1.out()!
}
cs
if let Kim = human(age:2, weight:17.5"actor") { 
//인스턴스생성과 동시에 옵셔널 바인딩
//코드가 간결해지고 많이는 방식
    Kim.out()!
}
cs

 

 

강제언래핑 방식

if let Kim = human(age:2, weight:17.5"actor")! //강제언래핑
//nil이 리턴될 경우 충돌발생
    Kim.out()!
 
cs
if let Kim? = human(age:2, weight:17.5"actor"//옵셔널형으로 저장
    Kim!.out() //강제언래핑
//nil이 리턴되면 충돌발생
cs

 

 

참고자료

 

iOS프로그래밍기초(21-2학기)한성현교수님 강의 내용

728x90
반응형

댓글