/**
생성자(Initializer)
구조체 vs 클래스 생성자
[구조체 생성자]
1. 지정 생성자, (자동제공되는 멤버와이즈생성자)
2. 실패가능생성자
[클래스 생성자]
1. 지정 생성자
2. 편의 생성자 (상속과 관련)
3. 필수 생성자 (상속과 관련)
4. 실패가능생성자
*/
// 일반적인 지정 생성자
struct Color {
let red, green, blue: Double
init() { // 기본 생성자. 기본값을 설정하면 자동으로 제공됨
red = 0.0
green = 0.0
blue = 0.0
}
init(white: Double) {
red = white
green = white
blue = white
}
init(red: Double, green: Double, blue: Double) {
self.red = red
self.green = green
self.blue = blue
}
}
// 구조체 생성자
// 구조체 (값타입)의 지정생성자의 구현
// 올바른 방식
// 유지보수 좋음.
struct Color1 {
let red, green, blue: Double
init() { // 구조체는 다른 생성자를 호출하는 방식도 있음
self.init(red: 0.0, green: 0.0, blue: 0.0)
}
init(white: Double) {
self.init(red: white, green: white, blue: white)
}
init(red: Double, green: Double, blue: Double) {
self.red = red
self.green = green
self.blue = blue
}
}
// 클래스 생성자
// 클래스의 지정(Designated: 데지그네이티드) vs 편의(Convenience: 컨비니언스) 생성자
class Color2 {
let red, green, blue: Double
// 편의 생성자
convenience init() {
self.init(red: 0.0, green: 0.0, blue: 0.0)
}
// 편의 생성자
convenience init(white: Double) {
self.init(red: white, green: white, blue: white)
}
init(red: Double, green: Double, blue: Double) {
self.red = red
self.green = green
self.blue = blue
}
}
/**
클래스는 상속을 지원하므로, 변수가 여러개 이고,
- 여러 지정 생성자를 지원했을때 상속 관계에서 개발자가 실수할 수 있는 여러가지 가능성이 있음.
- 따라서, 초기화 과정을 조금 간편하게 만들고,
- 상속관계에서 개발자가 실수 할 수 있는 여러가능성을 배제하기 위한 생성자임
* (이미 모든 속성을 초기화하는 지정생성자가 있다면) 모든 속성을 초기화하지 않는 경우 편의생성자로 구현을 권장
*/
/**
클래스의 상속과 지정 / 편의 생성자 사용 예시
*/
class Aclass {
var x: Int
var y: Int
init(x: Int, y: Int) { // 지정생성자 - 모든 저장 속성 설정
self.x = x
self.y = y
}
// 편의 생성자는 상속이 되지 않는다.
convenience init() { // 편의생성자 - (조금 편리하게 생성) 모든 저장 속성을 설정하지 않음
self.init(x: 0,y: 0)
}
}
// 상속이 일어나는 경우
class BClass: Aclass {
var z: Int
// 지정 생성자인 경우 반드시 재정의 해줘야한다.
init(x: Int, y: Int, z: Int) { // 실제 메모리에 초기화 되는 시점
self.z = z // 필수
super.init(x: x, y: y) // 필수 - 상위의 지정생성자 호출
// self.doSomething()
}
convenience init(z: Int) {
self.init(x: 0, y: 0, z: z)
}
convenience init() {
self.init(z: 0)
}
func doSomething() {
print("Do something")
}
}