[Swift 톺아보기] Convince init은 왜 사용하는 걸까?

kio·2023년 6월 12일
0

Swift

목록 보기
7/11
post-thumbnail

제목에서도 봤겠지만 convince init은 왜 사용하는 걸까?

Convenience initializers are written in the same style, but with the convenience modifier placed before the init keyword, separated by a space

아주 간단한 정의지만 처음 봤을때 굳이 사용하나 싶었다.

class introduce {
    var age: Int
    var name: String
    
    init(name: String, age: Int) {
        self.age = age
        self.name = name
    }
    
    convenience init(age: Int){
        self.init(name: "unknown", age: age)
    }
    
    func say(){
        print("Hello, my name is \(name)\n and i'm \(age)years old")
    }
}

이렇게 특정파라미터를 생략하는 방법이면 굳이 위처럼 하는 것보다

class introduce {
    var age: Int
    var name: String
    
    init(name: String = "unknown", age: Int) {
        self.age = age
        self.name = name
    }
    
    func say(){
        print("Hello, my name is \(name)\n and i'm \(age)years old")
    }
}

이게 더 간단해 보였다. 그래서 convenience을 만든 이유에 대해 고민을 해봤다.

1. 파라미터에 다양한 타입을 넣어서 대채할 수 있다.

나이를 세는 방법이 특이한 소수민족이 있다고 해보자, 그 소수민족은 복잡한 계산식을 통해 나이를 측정한다.

class introduce {
    var age: Int
    var name: String
    
    init(name: String = "unknown", age: Int) {
        self.age = age * 12498723895 / 2304798325 - 128347 + 123
        self.name = name
    }
    
    func say(){
        print("Hello, my name is \(name)\n and i'm \(age)years old")
    }
}

근데 이 부족에게도 MZ세대는 있는 법이다. 요즘 유행하는 나이 계산법인 소수점 나이 계산을 통해서 계산을 할려고 한다. 식은 갖지만 값이 소수점인 것이다.
그럼 우리는 몇가지 방법을 통해 문제를 해결할 수 있다.
1번은 parameter로 age와 floatAge를 만들어서 그 중에 nil이 아닌 것을 사용하는 방법
하지만 이건 딱 들어도 구리고 쓸모 없는 변수가 늘어난다.

그럼 2번

class Introduce {
    var age: Int
    var name: String
    
    init(name: String, age: Int) {
        self.age = age * 12498723895 / 2304798325 - 128347 + 123
        self.name = name
    }
    
    init(name: String, age: Float){
        self.age = Int(age * 12498723895 / 2304798325 - 128347 + 123)
        self.name = name
    }
    
    func say(){
        print("Hello, my name is \(name)\n and i'm \(age)years old")
    }
}

뭐 대충 형변환 해서 사용하는 방법인데 이는 구려보인다. 똑같은 일을 반복하는 코드가 있는 것뿐이라 문제가 생긴다.
만약 나이 계산이 더 복잡해진다면 저렇게 하기도 힘들 것이다.
그래서

class Introduce {
    var age: Int
    var name: String
    
    init(name: String, age: Int) {
        self.age = age * 12498723895 / 2304798325 - 128347 + 123
        self.name = name
    }
    
    convenience init(age: Float){
        self.init(name: "unknown", age: 수식생략(age))
    }
    
    func say(){
        print("Hello, my name is \(name)\n and i'm \(age)years old")
    }
}

똑같은 나이계산을 할더라도 훨씬 간편하고 디버깅도 쉬워질 것이다.

이것이 1번 이유이다. 타입이 다른 변수를 바꾸거나 추가하기 편하다는 장점이 있고, 이렇게 되면 자연스럽게 OCP도 적용할 수 있다.

2. Extesion에서 사용가능하다!

UIColor의 초기화는 다음과 같다.

public init(white: CGFloat, alpha: CGFloat)

public init(hue: CGFloat, saturation: CGFloat, brightness: CGFloat, alpha: CGFloat)

public init(red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat)

자 우리는 int ( 0 <= x <= 255)인 값으로도 초기화 할 수 없다 얼마나 불편해...
하지만 convenience init은 init chain을 활용하고 때문에 원본 즉 UIColor의 내부구조를 건들지 않으면서 init을 변경할 수 있다.

extension UIColor {
	convenience init(red: Int, green: Int, blue: Int) {
		self.init(red: CGFloat(red) / 255.0, ... )
	}
}

0개의 댓글