- ํด๋์ค์ ์คํธ๋ญ์ฒ๋ ์ธ์คํด์ค๊ฐ ์์ฑ๋๋ ์์ ์ ๋ชจ๋ stored property๊ฐ ์ด๊ธฐํ๋์ด์ผ ํ๋ค.
- ์ต์ ๋ ํ๋กํผํฐ๋ํ nil๋ก ์ด๊ธฐํ ๋๋ ๊ฒ์ด๋ค.
- ๊ธฐ๋ณธ๊ฐ์ ํ ๋นํ๋ 2๊ฐ์ง ๋ฐฉ๋ฒ(์ ์์ ๋์์ ํ ๋น, ์์ฑ์์์ ํ ๋น) ๋๋ค ํ๋กํผํฐ ์ต์ ๋ฒ๋ฅผ ํธ์ถํ์ง ์๋๋ค.
- ์๋ ์ฝ๋์์ willSet๊ณผ didSet์
a.height = 40
์ ํ๋ฒ๋ง ํธ์ถ๋จ
struct Person {
var height = 170 { //์ฌ๊ธฐ์ 170์ด ํ ๋น๋์ง๋ง ํ๋กํผํฐ ์ต์ ๋ฒ ํธ์ถ X
didSet {
print(oldValue)
}
willSet {
print(newValue)
}
}
init() {
self.height = 30 //์ฌ๊ธฐ์ 30์ด ํ ๋น๋์ง๋ง ํ๋กํผํฐ ์ต์ ๋ฒ ํธ์ถ X
}
}
var a = Person()
a.height = 40
- ๊ฒฐ๊ณผ
40
30
Program ended with exit code: 0
-
๊ตฌ์กฐ์ฒด๋ ํด๋์ค์์ ๋ชจ๋ ํ๋กํผํฐ๊ฐ ๊ธฐ๋ณธ๊ฐ์ ๊ฐ๊ณ ์๊ฑฐ๋ ์ต์ ๋์ด๊ณ ์์ฑ์๋ฅผ ํ๋๋ ๊ตฌํํ์ง ์์๋ค๋ฉด Default Initializer๊ฐ ์คํ๋๋ค.
-
Default Initializer = ๋ชจ๋ ํ๋กํผํฐ์ ๊ฐ์ ๊ธฐ๋ณธ๊ฐ(default value)๋ก ํ ๋นํด์ฃผ๊ณ ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ ์์ฑ์
-
์์, init()์ ๊ตฌํํ์ง ์์์ง๋ง ๊ธฐ๋ณธ๊ฐ์ ํ ๋นํด์ฃผ๋ Default ์์ฑ์๊ฐ ํธ์ถ๋จ
class ShoppingListItem {
var name: String?
var quantity = 1
var purchased = false
}
var item = ShoppingListItem()
- ๊ตฌ์กฐ์ฒด์์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณตํ๋ ์์ฑ์
- ์ด๋ฏธ ๊ธฐ๋ณธ๊ฐ์ด ํ ๋น๋ ๋ณ์๋ ์๋ตํ ์ ์๋ค.
- ์์
struct Size {
var width = 0.0, height = 0.0
}
//width, height ๋๋ค ํ ๋น
let twoByTwo = Size(width: 2.0, height: 2.0)
//width ์๋ต
let zeroByTwo = Size(height: 2.0)
//height ์๋ต
let zeroByZero = Size()
-
Initializer Delegation = ์์ฑ์ ์์์ ๋ค๋ฅธ ์์ฑ์๋ฅผ ํธ์ถํ๋ ์ฝ๋
-
Initializer Delegation์ Value type๊ณผ class type ๋๋ค ์์
-
Value type์ ์์์ด ์๊ธฐ๋๋ฌธ์ ๊ท์น์ด ๋ ๋จ์ํจ
-
Initializer Delegation์ด ์ผ์ด๋๋ ์ฝ๋์์๋ Convenience ํค์๋๊ฐ ํ์์์
-
Custom ์์ฑ์๋ฅผ value type์ ์ ์ํ๋ฉด, ๋ ์ด์ ๊ธฐ๋ณธ ์์ฑ์๋ฅผ ์ฌ์ฉํ ์ ์์
- ๊ตฌ์กฐ์ฒด๋ผ๋ฉด ๋ฉค๋ฒ์์ด์ฆ ์์ฑ์ ๋ํ ์ ๊ทผ ๋ชปํจ
- Custom ์์ฑ์์ ๊ธฐ๋ณธ ์์ฑ์๋ฅผ ๋๋ค ์ฌ์ฉํ๊ณ ์ถ๋ค๋ฉด Custom ์์ฑ์๋ฅผ extension์ ์ ์ํ๋ฉด ๋จ
-
์์
struct Size {
var width = 0.0, height = 0.0
}
struct Point {
var x = 0.0, y = 0.0
}
struct Rect {
var origin = Point()
var size = Size()
init() {}
init(origin: Point, size: Size) {
self.origin = origin
self.size = size
}
//์ด๋ถ๋ถ์์ delegation์ด ์ผ์ด๋จ. ํ์ง๋ง convenience ํค์๋๊ฐ ํ์์์
init(center: Point, size: Size) {
let originX = center.x - (size.width / 2)
let originY = center.y - (size.height / 2)
self.init(origin: Point(x: originX, y: originY), size: size)
}
}
- ํด๋์ค์๋ง convenience init๊ณผ designated init์ด ์์
- ๋ชจ๋ ํด๋์ค์๋ ์ต์ ํ๊ฐ์ designated ์์ฑ์๊ฐ ์์ด์ผํจ
- ๊ฐ์ ํด๋์ค์ ๋ค๋ฅธ ์์ฑ์๋ฅผ ํธ์ถํ๋ ค๋ฉด convenience init์ผ๋ก ๋ง๋ค์ด์ผ ํ๋ค.
Rule 1 A designated initializer must call a designated initializer from its immediate superclass. Rule 2 A convenience initializer must call another initializer from the same class. Rule 3 A convenience initializer must ultimately call a designated initializer.
A simple way to remember this is:
- Designated initializers must always delegate up.
- Convenience initializers must always delegate across.
- ๊ฐ์ ํด๋์ค์ ๋ค๋ฅธ ์์ฑ์๋ฅผ ํธ์ถํ๋ ค๋ฉด convenience ํค์๋๊ฐ ํ์ํจ
- ์์ ํด๋์ค์ ์์ฑ์(super.init())์ designated ์์ฑ์์์๋ง ๊ฐ๋ฅํ๊ณ ์ฌ๊ธฐ์ ๋ถ๋ ค์ง๋ ์์ฑ์ ๋ํ designated ์์ฑ์๋ง ๊ฐ๋ฅํจ
- ํด๋์ค์ ์ด๊ธฐํ๋ 2๋จ๊ณ๋ก ์ด๋ฃจ์ด์ง
1 phase๋ ์๋ก ์ฌ๋ผ๊ฐ๋ ๊ณผ์ 2 phase๋ ์๋๋ก ๋ด๋ ค๊ฐ๋ ๊ณผ์
- ํด๋น ๊ฐ์ฒด์ ๋ฉ์๋์๋ 2phase์์๋ง ์ ๊ทผํ ์ ์๋ค.
- ์์ ํด๋์ค์ ํ๋กํผํฐ๋ ๋ฉ์๋๋ 2phase์์๋ง ์ ๊ทผํ ์ ์๋ค.
- ํด๋น ๊ฐ์ฒด์ ํ๋กํผํฐ๋ 1phase, 2phase ๋๋ค ์ ๊ทผํ ์ ์๋ค.
- ํ์ ํด๋์ค์ ๋ชจ๋ ํ๋กํผํฐ๊ฐ ์ด๊ธฐํ ๋์ง ์์ผ๋ฉด ์์ํด๋์ค์ designated initializer๋ ํธ์ถ๋์ง ๋ชปํ๋ค.
- ์ค์ต ์ฝ๋
import UIKit
class Parent {
var name: String
init(name: String) {
self.name = name
}
func say() {
print("haha")
}
}
class Child: Parent {
var childName: String
init(childName: String) {
self.childName = childName
print(self.childName)
//----------์ฌ๊ธฐ๊น์ง 1phase
//์ฌ๊ธฐ์๋ ์ด ๊ฐ์ฒด์ ๋ฉ์๋์ ์ ๊ทผ ๋ถ๊ฐ
//์์ ํด๋์ค์ ๊ทธ ์ด๋ค๊ฒ๋ ์ ๊ทผ ๋ถ๊ฐ
//์ค์ง ์ด ๊ฐ์ฒด์ ํ๋กํผํฐ๋ง ์ ๊ทผ๊ฐ๋ฅ
super.init(name: "papa")
//-----------------------------
//----------์ฌ๊ธฐ๋ถํฐ 2phase
super.say()
super.name = "hihi"
print(self.name)
self.sayHi()
}
convenience init(age: Int) {
self.init(childName: "child")
self.childName = "hihi"
}
func sayHi() {
print("HI")
}
}
Safety check 1 ์์ ํด๋์ค์ ์์ฑ์๋ฅผ ํธ์ถํ๊ธฐ์ ์ ํด๋น ํด๋์ค์ ๋ชจ๋ ํ๋กํผํฐ๊ฐ ์ด๊ธฐํ๋์ด์ผํจ ํด๋์ค๊ฐ ์์ฑ๋ ๋ ๋ชจ๋ ์ ์ฅ ํ๋กํผํฐ์ ๊ฐ์ ์์์ผ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋นํ ์ ์์. ๋ฐ๋ผ์ ํด๋น ํด๋์ค์ designated ์์ฑ์๊ฐ ๋ชจ๋ ์ ์ฅ ํ๋กํผํฐ์ ๊ฐ์ด ์ด๊ธฐํ๋์๋์ง ํ๋จํจ
Safety check 2 ํ์ ํด๋์ค์์ ์์ํด๋์ค๋ก๋ถํฐ ์์๋ ํ๋กํผํฐ์ ์ ๊ทผํ๋ ค๋ฉด designated initializer๋ ๋ธ๋ฆฌ๊ฒ์ดํธ ์ ์ผ๋ก ์์ ํด๋์ค์ ์์ฑ์๋ฅผ ๋จผ์ ํธ์ถํด์ผ ํจ. ๊ทธ๋ ์ง ์์ผ๋ฉด(ํ์ ํด๋์ค์์ ์์ํด๋์ค์ ํ๋กํผํฐ ๊ฐ์ ํ ๋นํ๋ฉด) ์ด์ฐจํผ ์์ํด๋์ค์ designated initializer์ ์ํด ๊ฐ์ด ๋ฎ์ด์์์ง <-
๊ทผ๋ฐ ์ด๊ฒ Xcode์์ ๋ฌธ๋ฒ์ ์ผ๋ก ๋ถ๊ฐ๋ฅํจ
Safety check 3 ์ปจ๋น๋์ธ์ค ์ด๋์ ๋ผ์ด์ ๋ ํ๋กํผํฐ์ ๊ฐ์ ํ ๋นํ๊ธฐ ์ ์ ๋ฌด์กฐ๊ฑด ๋ค๋ฅธ ์ด๋์ ๋ผ์ด์ ๋ฅผ ํธ์ถํด์ ๋ชจ๋ ํ๋กํผํฐ์ ๊ฐ์ด ํ ๋น๋์ด์ผ ํ๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ํ ๋น๋ ๊ฐ์ด ๋ค๋ฅธ ์ด๋์ ๋ผ์ด์ ์ ์ํด ๋ฎ์ด์์์ง <-
๊ทผ๋ฐ ์ด๊ฒ Xcode์์ ๋ฌธ๋ฒ์ ์ผ๋ก ๋ถ๊ฐ๋ฅํจ
Safety check 4 ์์ฑ์๋ 1 phase initialization์ด ์๋ฃ๋๊ธฐ ์ ์ ๋ค์๊ณผ ๊ฐ์ ํ๋์ ํ ์ ์๋ค. ์ธ์คํด์ค์ ๋ฉ์๋ ํธ์ถ, ์ธ์คํด์ค์ ํ๋กํผํฐ ์ ๊ทผ, self๋ฅผ ๊ฐ์ผ๋ก์จ ์ ๊ทผ 1 phase initialization์ด ์๋ฃ๋ ์์ ์ ํด๋์ค์ ์ธ์คํด์ค๊ฐ ์์ ํ ์์ฑ๋ ์๊ธฐ๊ฐ ์๋์ง๋ง ์ธ์คํด์ค ํ๋กํผํฐ์ ์ ๊ทผ, ๋ฉ์๋ ํธ์ถ์ด ๊ฐ๋ฅํ๋ค.
- ํ์ ํด๋์ค๊ฐ ์์ ํด๋์ค์ ๊ฐ์ ์์ฑ์๋ฅผ ๋ง๋ค ๋ override ํค์๋๋ฅผ ์จ์ผํ๋ค.
- ์ด๋ ํ์ํด๋์ค์ ๊ฐํธ ์์ฑ์๊ฐ ์์ ํด๋์ค์ ์ง์ ์์ฑ์์ ๊ฐ์ ๊ฒฝ์ฐ์๋ ๋ง์ฐฌ๊ฐ์ง๋ค.
- ํ์ํด๋์ค์ ์ง์ ์์ฑ์๊ฐ ์์ํด๋์ค์ ๊ฐํธ์์ฑ์๊ฐ ๊ฐ์ ๊ฒฝ์ฐ์๋ overrideํค์๋๋ฅผ ์ธ ํ์๊ฐ ์๋ค.
- ํ์ํด๋์ค์ ๊ฐํธ์์ฑ์๊ฐ ํ์ํด๋์ค์ ์ง์ ์์ฑ์๋ฅผ ๋ฐ๋ก ํธ์ถํ ์๊ฐ ์๊ธฐ๋๋ฌธ์ overrideํ๋๊ฒ ์๋๋ผ๊ณ ํจ
๊ฒฝ์ฐ1) ํ์์ ์ง์ ์์ฑ์๊ฐ ์์์ ์ง์ ์์ฑ์๋ฅผ overrideํ๋๊ฒฝ์ฐ -> override ํค์๋ ํ์ํจ
class Animal {
let name: String
init(name: String) {
self.name = name
}
}
class Dog: Animal {
override init(name: String) { //override ์์ฐ๋ฉด ์๋ฌ๋จ
super.init(name: name)
}
}
๊ฒฝ์ฐ2) ํ์์ ๊ฐํธ์์ฑ์๊ฐ ์์์ ์ง์ ์์ฑ์์ ๊ฐ์๊ฒฝ์ฐ -> override ํค์๋ ํ์ํจ
class Animal {
let name: String
init(name: String) {
self.name = name
}
init(lastName: String) {
self.name = "kim" + lastName
}
}
class Dog: Animal {
let age: Int
init(name: String, age: Int) {
self.age = age
super.init(name: name)
}
override convenience init(lastName: String) {
self.init(name: "kim" + lastName, age: 30)
}
}
๊ฒฝ์ฐ3) ํ์์ ์ง์ ์์ฑ์๊ฐ ์์์ ๊ฐํธ์์ฑ์์ ๊ฐ์ ๊ฒฝ์ฐ -> override ํค์๋ ํ์์์
class Animal {
let name: String
init(name: String) {
self.name = name
}
convenience init(lastName: String) {
self.init(name: "noName" + lastName)
}
}
class Dog: Animal {
let age: Int
init(lastName: String) { //override ์ฐ๋ฉด ์๋ฌ๋จ
self.age = 30
super.init(name: "pikachu")
}
}
๊ฒฝ์ฐ3) ํ์์ ๊ฐํธ์์ฑ์๊ฐ ์์์ ๊ฐํธ์์ฑ์์ ๊ฐ์๊ฒฝ์ฐ -> override ํค์๋ ํ์์์
class Animal {
let name: String
init(name: String) {
self.name = name
}
convenience init(lastName: String) {
self.init(name: "noName" + lastName)
}
}
class Dog: Animal {
let age: Int
init(name: String, age: Int) {
self.age = age
super.init(name: name)
}
convenience init(lastName: String) {//override ํค์๋ ํ์์์
self.init(name: "noName" + lastName, age: 30)
}
}
ํ์ ํด๋์ค์ ์์ฑ์ | ์์ ํด๋์ค์ ์์ฑ์ | override ํค์๋ ์ฌ๋ถ |
---|---|---|
์ง์ | ์ง์ | override ํ์ํจ |
๊ฐํธ | ์ง์ | override ํ์ํจ |
์ง์ | ๊ฐํธ | override ํ์์์ |
๊ฐํธ | ๊ฐํธ | override ํ์์์ |
- ํ์ ํด๋์ค๊ฐ phase 2์์ ์๋ฌด๋ฐ ํ ์ผ์ด ์๊ณ (์์ํด๋์ค์ ํ๋กํผํฐ๋ฅผ ์์ ํ์ง ์๊ณ ํ์ฌ ํด๋์ค์ ๋ฉ์๋์ ์ ๊ทผํ์ง ์์๋), ๊ทธ๋ฆฌ๊ณ ์์ ํด๋์ค์ ์ง์ ์์ฑ์๊ฐ argument๊ฐ ์์๋ super.init()์ ์๋ตํ ์ ์๋ค.
- ์๋๋ ์์
class Vehicle {
var numberOfWheels = 0
var description: String {
return "\(numberOfWheels) wheel(s)"
}
}
class Hoverboard: Vehicle {
var color: String
init(color: String) {
self.color = color
// super.init() implicitly called here
//๋ง์ฝ ์์ ํด๋์ค์ ํ๋กํผํฐ์ ์ ๊ทผํ๊ณ ์ถ์ผ๋ฉด super.init()์ ๋ช
์ํด์ผํจ
}
override var description: String {
return "\(super.description) in a beautiful \(color)"
}
}
-
ํ์ ํด๋์ค๋ ์์ํด๋์ค์ ์ง์ ์์ฑ์๋ฅผ ๊ธฐ๋ณธ์ ์ผ๋ก ์์ํ์ง ์๋๋ค.(ํน์ ์กฐ๊ฑด์์๋ง ์์ํจ)
-
ํ์ ํด๋์ค์์ ์๋ก์ด ํ๋กํผํฐ๋ฅผ ๋ง๋ค์์ ๋ ๋ค์ 2๊ฐ์ง ๋ฃฐ์ด ์ ์ฉ๋จ
- ์ฒซ๋ฒ์งธ ๋ฃฐ
- ํ์ ํด๋์ค์์ ์ง์ ์์ฑ์๋ฅผ ๋ง๋ค์ง ์์ผ๋ฉด ์์ ํด๋์ค์ ๋ชจ๋ ์ง์ ์์ฑ์๊ฐ ์์๋จ
- ๋๋ฒ์งธ ๋ฃฐ
- ํ์ ํด๋์ค์์ ์ํผํด๋์ค์ ๋ชจ๋ ์ง์ ์์ฑ์๋ฅผ ๋ง๋ค๋ฉด(์ฒซ๋ฒ์ฌ ๋ฃฐ์ ์ํด ์์๋ ๊ฒฝ์ฐ ํฌํจ) ์์ ํด๋์ค์ ๋ชจ๋ ๊ฐํธ ์์ฑ์๊ฐ ์์๋จ
- ์ด๋ ์๋ธํด๋์ค์์ ์ถ๊ฐ์ ์ธ ๊ฐํธ์์ฑ์๋ฅผ ๋ง๋ ๊ฒฝ์ฐ๋ ํฌํจ๋๋ค.
- ์ฒซ๋ฒ์งธ ๋ฃฐ
NOTE
A subclass can implement a superclass designated initializer as a subclass convenience initializer as part of satisfying rule 2.