본문 바로가기

Swift

Initialization - 그 외

728x90

실패 가능한 초기자

초기화 과정 중에서 실패할 가능성이 있는 초기자를 init 뒤에 물음표를 통해 실패가 가능한 초기자라고 표시할 수 있습니다.

 

✔️ 초기자는 이름이 따로 있는 것이 아니라 파리미터로 구분하기 때문에 실패 가능한 초기자와 실패 불가능한 초기자를 같은 파라미터 타입과 이름으로 동시에 사용할 수 없습니다. 실패 가능한 초기자는 반환값으로 옵셔널 값을 생성합니다. 초기화에 실패하는 부분에서 nil을 반환하여 초기화가 실패했다는 것을 알 수 있습니다.

✔️ 엄밀히 말하자면 초기자 init은 값을 반환하지 않습니다. 그래서 비록 nil을 반환하는 return nil 코드에는 사용되지만 init이 성공한 경우 return 키워드를 사용하지 않습니다.

 

아래의 코드는 숫자형을 위해 정의되어 있는 실패 가능한 초기자 init을 사용한 예제입니다.

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"

 

아래의 코드는 Animal 구조체를 만들어 인자를 넣은 경우(초기화에 성공한 경우)와 인자를 넣지 않고 생성한 경우(초기화에 실패한 경우)를 나타낸 예제입니다.

// Animal 구조체를 생성 
struct Animal {
    let species: String
    
    init?(species: String) {
        if species.isEmpty { return nil }
        self.species = species
    }
}

// 동물의 종류를 Giraffe로 지정
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 could not be initialized")
}
// Prints "The anonymous creature could not be initialized"

📌 empty와 nil은 다릅니다. 그래서 .isEmpty를 이용해서 비교하지 않으면 인스턴스 초기화 시 ""을 넣어도 초기화가 됩니다. 이것은 의도한 것이 아니기 때문에 .isEmpty를 통해서 empty의 값을 확인하여 nil을 반환하도록 구현해야 합니다. 


필수 초기자

모든 서브 클래스에서 반드시 구현해야 하는 초기자에는 아래와 같이 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
    }()
}

'Swift' 카테고리의 다른 글

atomic VS nonatomic  (0) 2022.04.26
Initialization - 구조체/클래스 초기화  (0) 2022.04.21
Initialization - 상속과 초기화  (0) 2022.04.20
Initialization - 무엇인가  (0) 2022.04.20
Hashable  (0) 2022.04.14