swift 0x0e
initialization
문현진(arnold@css99.co.kr)
초기자
init
초기자
struct Fahrenheit {
var temperature: Double
init() {
temperature = 32.0
}
}
기본 속성 값
struct Fahrenheit {
var temperature = 32.0
}
사용자 정의 초기화 - 초기화 파라메터
struct Celsius {
var temperatureInCelsius: Double = 0.0
init(fromFahrenheit fahrenheit: Double) {
temperatureInCelsius = (faherenheit - 32.0)/1.8
}
}
사용자 정의 초기화 - 지역 파라메터
struct Color {
let red = 0.0, green = 0.0, blue = 0.0
init(red: Double, green: Double, blue: Double) {
self.red = red
self.green = green
self.blue = blue
}
}
사용자 정의 초기화 - 외부 파라메터
let magenta = Color(red: 1.0, green: 0.0, blue: 1.0)
let veryGreen = Color(0.0, 1.0, 0.0)
init 의 파라메터는 기본적으로
지역 파라메터 + 외부 파라메터 이다.
옵셔널 속성 타입
class SurveyQuestion {
var text: String
var response: String?
init(text: String) {
self.text = text
}
func ask() {
println(text)
}
}
옵셔널 속성 타입
let cheeseQuestion =
SurveyQuestion(text: “Do you like
cheese?”)
cheeseQuestion.ask()
cheeseQuestion.response = “Yes, I do
like cheese.”
class SurveyQuestion {
let text: String
var response: String?
init(text: String) {
self.text = text
}
func ask() {
println(text)
}
}
초기화 과정중에 상수 속성을 변경하기
let cheeseQuestion =
SurveyQuestion(text: “How about
beets??”)
cheeseQuestion.ask()
cheeseQuestion.response = “I also
like beets.”
기본 초기자
class ShoppingListItem {
var name: String?
var quantity = 1
var purchased = false
}
var item = ShoppingListItem()
모든 속성은 기본 값을 가져야 합니다.
옵셔널은 자동 기본값으로 nil을 받습
니다.
구조체 타입의 멤버 단위 초기화
struct Size {
var width = 0.0, height = 0.0
}
let twoByTwo = Size(width: 2.0,
height: 2.0)
모든 속성에 기본값이 있고,
사용자 정의 초기자가 없으면
=> 구조체 타입은 자동으로 멤버 단위
초기자를 가진다.
값 타입 = 구조체, 열거자
값 타입의 초기자 대리자
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
}
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)
}
}
정사각형을 그리는 방법은 3가지가 있다.
1. (0, 0)에 위치하는 크기 0 짜리 정사각형
2. (x, y)에 위치하는 크기 n 짜리 정사각형
3. (x, y)를 중심으로하는 크기 n짜리 정사각
형
이 초기화 시나리오이다. 3번 째 초기자에
서, 2번째 초기자를 호출 또는 대리 한다.
클래스 상속과 초기화
클래스의 모든 속성은 반드시 초기 값이 있어야 한다
클래스 상속과 초기화
지정 초기자
주 초기자
모든 속성을 완전히 초기화
+
적절한 부모 클래스 초기자 호출
모든 클래스는 반드시 하나 이상의 지정 초기자를
가져야 한다.
편의 초기자
부 초기자
같은 클래스내의 지정 초기자를 호출하는 초기자
호출하는 지정 초기자의 몇몇 파라메터를 기본으
로 하는 초기자
특정 용도나 입력 값 타입에 대한 클래스 인스턴스
를 만드는 초기자
클래스 상속과 초기화
1 Phase
해당 클래스가 가지는 저장속성에 초기값을 할당 한다.
2 Phase
클래스 인스턴스를 사용할 준비가 되기 전까지 속성 값을 변경한다.
두 단계 초기화
안전 점검 1
부모 클래스의 초기자를 위임하기 전에, 내 클래
스의 속성이 초기화 되었는지 확인한다.
안전 점검 2
지정 초기자는 상속받은 속성에 값을 할당하기 전
에 부모 클래스의 초기자를 수행해야 합니다. (값
이 부모 클래스의 초기화 중에 덮어씌워진다.)
안전 점검 3
편의 초기자는 속성에 값을 할당하기전에 다른 초
기자를 대리 수행 해야 합니다. 그렇지 않으면 편
의 초기자가 할당한 값은 지정 초기자에 의해 덮어
씌워집니다.
안전 점검 4
초기자는 인스턴스 메소드를 호출 할 수 없습니다.
초기화 첫 단계가 끝나기 전에는 self도 참조 할 수
없습니다.
두 단계 초기화
Phase 1
두 단계 초기화
Phase 2
두 단계 초기화
swift의 자식 클래스는 기본적으로 부모 클래스의 초기자를 상속 받지 않습니다
.
(=! object-C)
초기자 상속과 오버라이딩
초기화 중간에 뭔가 수정 하기 위해서, 부모 클래스와 같은 초기자를 가진 자식
클래스가 필요 할 때, 자식 클래스에 같은 초기자를 오버라이딩 해서 구현 할 수
있습니다.
오버라이딩 하는 초기자가 지정 초기자라면, 오자식 클래스에서 구현체를 오버
라이드 하고, 오버라이딩 하는 버전에서 부모 버전의 초기자를 호출 하도록 할
수 있습니다.
초기자 상속과 오버라이딩
Rule 1
자식 클래스가 지정 초기자를 정의하지 않는다.
Rule 2
자식 클래스가 부모 클래스의 모든 지정 초기자를 구현한다.
초기자 자동 상속
편의 초기자는 convenience를 사용합
니다.
convenience init(parameters) {
statements
}
클래스의 지정 초기자는 값 타입을 위
한 단순 초기자와 같은 방식으로 작성
한다.
init(parameters) {
statements
}
지정 초기자, 편의 초기자의 문법
class Food {
var name: String
init(name: String) {
self.name = name
}
convenience init() {
self.init(name: “[Unnamed]”)
}
}
지정 초기자와 편의 초기자 실습
class RecipeIngredient: Food {
var quantity: Int
init(name:String, quantity: Int) {
self.quantity = quantity
super.init(name: name)
}
convenience init(name: String) {
self.init(name: name, quantity: 1)
}
}
지정 초기자와 편의 초기자 실습
지정 초기자와 편의 초기자 실습
class RecipeIngredient: Food {
var quantity: Int
init(name:String, quantity: Int) {
self.quantity = quantity
super.init(name: name)
}
convenience init(name: String) {
self.init(name: name, quantity: 1)
}
}
지정 초기자와 편의 초기자 실습
class RecipeIngredient: Food {
var quantity: Int
init(name:String, quantity: Int) {
self.quantity = quantity
super.init(name: name)
}
convenience init(name: String) {
self.init(name: name, quantity: 1)
}
}
지정 초기자와 편의 초기자 실습
let oneMysteryItem =
RecipeIngreidnet()
let oneBacon =
RecipeIngredient(name:
“Bacon”)
let sixEggs =
RecipeIngredient(name: “Eggs”,
quantity: 6)
지정 초기자와 편의 초기자 실습
class ShoppingListItem: RecipeIngredient {
var purchased = false
var description: String {
var output = “(quantity) x
(name.lowercaseString)”
output += purchased ? “V” : “X”
return output
}
}
지정 초기자와 편의 초기자 실습
class SomeClass {
let someProperty: SomeType = {
return someValue}()
}
클로저나 함수로 기본 속성 값을 설정하
기
클로저나 함수로 기본 속성 값을 설정하
기
클로저나 함수로 기본 속성 값을 설정하
기

Swift 0x0e 초기화

  • 1.
  • 2.
  • 3.
    초기자 struct Fahrenheit { vartemperature: Double init() { temperature = 32.0 } }
  • 4.
    기본 속성 값 structFahrenheit { var temperature = 32.0 }
  • 5.
    사용자 정의 초기화- 초기화 파라메터 struct Celsius { var temperatureInCelsius: Double = 0.0 init(fromFahrenheit fahrenheit: Double) { temperatureInCelsius = (faherenheit - 32.0)/1.8 } }
  • 6.
    사용자 정의 초기화- 지역 파라메터 struct Color { let red = 0.0, green = 0.0, blue = 0.0 init(red: Double, green: Double, blue: Double) { self.red = red self.green = green self.blue = blue } }
  • 7.
    사용자 정의 초기화- 외부 파라메터 let magenta = Color(red: 1.0, green: 0.0, blue: 1.0) let veryGreen = Color(0.0, 1.0, 0.0) init 의 파라메터는 기본적으로 지역 파라메터 + 외부 파라메터 이다.
  • 8.
  • 9.
    class SurveyQuestion { vartext: String var response: String? init(text: String) { self.text = text } func ask() { println(text) } } 옵셔널 속성 타입 let cheeseQuestion = SurveyQuestion(text: “Do you like cheese?”) cheeseQuestion.ask() cheeseQuestion.response = “Yes, I do like cheese.”
  • 10.
    class SurveyQuestion { lettext: String var response: String? init(text: String) { self.text = text } func ask() { println(text) } } 초기화 과정중에 상수 속성을 변경하기 let cheeseQuestion = SurveyQuestion(text: “How about beets??”) cheeseQuestion.ask() cheeseQuestion.response = “I also like beets.”
  • 11.
    기본 초기자 class ShoppingListItem{ var name: String? var quantity = 1 var purchased = false } var item = ShoppingListItem() 모든 속성은 기본 값을 가져야 합니다. 옵셔널은 자동 기본값으로 nil을 받습 니다.
  • 12.
    구조체 타입의 멤버단위 초기화 struct Size { var width = 0.0, height = 0.0 } let twoByTwo = Size(width: 2.0, height: 2.0) 모든 속성에 기본값이 있고, 사용자 정의 초기자가 없으면 => 구조체 타입은 자동으로 멤버 단위 초기자를 가진다.
  • 13.
    값 타입 =구조체, 열거자 값 타입의 초기자 대리자 struct Size { var width = 0.0, height = 0.0 } struct Point { var x = 0.0, y = 0.0 }
  • 14.
    값 타입의 초기자대리자 struct Rect { var origin = Point() var size = Size() init() {} init(origin: Point, size:Size) { self.origin = origin self.size = size } 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) } } 정사각형을 그리는 방법은 3가지가 있다. 1. (0, 0)에 위치하는 크기 0 짜리 정사각형 2. (x, y)에 위치하는 크기 n 짜리 정사각형 3. (x, y)를 중심으로하는 크기 n짜리 정사각 형 이 초기화 시나리오이다. 3번 째 초기자에 서, 2번째 초기자를 호출 또는 대리 한다.
  • 15.
    클래스 상속과 초기화 클래스의모든 속성은 반드시 초기 값이 있어야 한다
  • 16.
    클래스 상속과 초기화 지정초기자 주 초기자 모든 속성을 완전히 초기화 + 적절한 부모 클래스 초기자 호출 모든 클래스는 반드시 하나 이상의 지정 초기자를 가져야 한다. 편의 초기자 부 초기자 같은 클래스내의 지정 초기자를 호출하는 초기자 호출하는 지정 초기자의 몇몇 파라메터를 기본으 로 하는 초기자 특정 용도나 입력 값 타입에 대한 클래스 인스턴스 를 만드는 초기자
  • 17.
  • 18.
    1 Phase 해당 클래스가가지는 저장속성에 초기값을 할당 한다. 2 Phase 클래스 인스턴스를 사용할 준비가 되기 전까지 속성 값을 변경한다. 두 단계 초기화
  • 19.
    안전 점검 1 부모클래스의 초기자를 위임하기 전에, 내 클래 스의 속성이 초기화 되었는지 확인한다. 안전 점검 2 지정 초기자는 상속받은 속성에 값을 할당하기 전 에 부모 클래스의 초기자를 수행해야 합니다. (값 이 부모 클래스의 초기화 중에 덮어씌워진다.) 안전 점검 3 편의 초기자는 속성에 값을 할당하기전에 다른 초 기자를 대리 수행 해야 합니다. 그렇지 않으면 편 의 초기자가 할당한 값은 지정 초기자에 의해 덮어 씌워집니다. 안전 점검 4 초기자는 인스턴스 메소드를 호출 할 수 없습니다. 초기화 첫 단계가 끝나기 전에는 self도 참조 할 수 없습니다. 두 단계 초기화
  • 20.
  • 21.
  • 22.
    swift의 자식 클래스는기본적으로 부모 클래스의 초기자를 상속 받지 않습니다 . (=! object-C) 초기자 상속과 오버라이딩
  • 23.
    초기화 중간에 뭔가수정 하기 위해서, 부모 클래스와 같은 초기자를 가진 자식 클래스가 필요 할 때, 자식 클래스에 같은 초기자를 오버라이딩 해서 구현 할 수 있습니다. 오버라이딩 하는 초기자가 지정 초기자라면, 오자식 클래스에서 구현체를 오버 라이드 하고, 오버라이딩 하는 버전에서 부모 버전의 초기자를 호출 하도록 할 수 있습니다. 초기자 상속과 오버라이딩
  • 24.
    Rule 1 자식 클래스가지정 초기자를 정의하지 않는다. Rule 2 자식 클래스가 부모 클래스의 모든 지정 초기자를 구현한다. 초기자 자동 상속
  • 25.
    편의 초기자는 convenience를사용합 니다. convenience init(parameters) { statements } 클래스의 지정 초기자는 값 타입을 위 한 단순 초기자와 같은 방식으로 작성 한다. init(parameters) { statements } 지정 초기자, 편의 초기자의 문법
  • 26.
    class Food { varname: String init(name: String) { self.name = name } convenience init() { self.init(name: “[Unnamed]”) } } 지정 초기자와 편의 초기자 실습
  • 27.
    class RecipeIngredient: Food{ var quantity: Int init(name:String, quantity: Int) { self.quantity = quantity super.init(name: name) } convenience init(name: String) { self.init(name: name, quantity: 1) } } 지정 초기자와 편의 초기자 실습
  • 28.
  • 29.
    class RecipeIngredient: Food{ var quantity: Int init(name:String, quantity: Int) { self.quantity = quantity super.init(name: name) } convenience init(name: String) { self.init(name: name, quantity: 1) } } 지정 초기자와 편의 초기자 실습
  • 30.
    class RecipeIngredient: Food{ var quantity: Int init(name:String, quantity: Int) { self.quantity = quantity super.init(name: name) } convenience init(name: String) { self.init(name: name, quantity: 1) } } 지정 초기자와 편의 초기자 실습
  • 31.
    let oneMysteryItem = RecipeIngreidnet() letoneBacon = RecipeIngredient(name: “Bacon”) let sixEggs = RecipeIngredient(name: “Eggs”, quantity: 6) 지정 초기자와 편의 초기자 실습
  • 32.
    class ShoppingListItem: RecipeIngredient{ var purchased = false var description: String { var output = “(quantity) x (name.lowercaseString)” output += purchased ? “V” : “X” return output } } 지정 초기자와 편의 초기자 실습
  • 33.
    class SomeClass { letsomeProperty: SomeType = { return someValue}() } 클로저나 함수로 기본 속성 값을 설정하 기
  • 34.
    클로저나 함수로 기본속성 값을 설정하 기
  • 35.
    클로저나 함수로 기본속성 값을 설정하 기

Editor's Notes

  • #8 지역 파라메터는 init 안에서만 쓸 수 있는 파라메터이다. 외부 파라메터는 외부에서 init을 호출 할 때 반드시 이름을 magenta 를 초기화 하는 것 처럼 명시해야 한다. 그래서 veryGreen은 오류이다.
  • #9 옵셔널은 그냥 int 가 아니라 int? / optional int 타입이다. toInt() 했을때 possibleNumber가 nil일 수 있다. 이 때 !를 통해서 강제 언래핑 하면 fatal exception이 발생 한다.
  • #11 클래스 인스턴스는 상수 속성의 값을 오직 초기화 과정중에 해당 클래스에 의해서만 바꿀 수 있습니다. 상수 속성은 자식(sub) 클래스에 의해 변경될 수 없습니다
  • #12 반드시 클래스의 모든 속성이 기본 값을 가지고 있어야 합니다. 그래야 자동으로 기본 초기자를 구현할 수 있습니다. 단, 옵셔널은 자동으로 기본값으로 nil을 받습니다.
  • #13 구조체 타입은 자동으로 멤버 단위 초기자를 가진다. 단, 모든 저장 속성에 기본 값이 제공되고, 사용자 정의 초기자가 없어야 한다.
  • #14 값 타입은 상속을 허용하지 않기 때문에 초기자를 대리하는게 상대적으로 쉽다. 왜냐하면 자기 자기가 가지고 있는 다른 초기자만 대리 할 수 있기 때문이다.
  • #18 초기자 연쇄 지정초기자는 반드시 바로 위 부모 클래스의 지정 초기자를 호출한다. 편의 초기자는 반드시 같은 클래스 내의 초기자를 호출한다. 편의 초기자는 반드시 지정 초기자를 호출하는 것으로 끝내야 한다.
  • #19  이렇게 두 단계 초기화를 함으로써, 초기화를 안전하게 하고, 상속 계층 상에서 유연성을 가진다. 속성 값이 초기화 되기 전에 접근하는 것을 반지, 다른 초기자 값을 설정하는 것을 방지 한다. 스위프트의 이 단계 초기화 과정은 오브젝티브 C의 초기화와 비슷합니다. 주요한 차이점은 첫번째 단계에 있습니다. 오브젝티브 C는 0이나 널(null) 값(0 또는 nil)을 모든 속성에 할당합니다. 스위프트의 초기화 흐름은 좀 더 유연하려 사용자 정의 초기값을 설정할 수 있게 해줍니다. 그리고 0이나nil이 기본값으로 유효하지 않은 타입에 대처할 수 있게 합니다.
  • #21 - 클래스의 지정 초기자 또는 편의 초기자 호출 - 클래스 인스턴스를 위한 메모리 할당 - 클래스 지정 초기자가 해당 클래스에있는 모든 저장속성이 값이 있는지 확인. 해당 저장 속성을 위한 메모리 초기화 완료. - 지정 초기자는 부모 클래스 지정 초기자로 작업을 넘겨줍니다. - 상속 계층의 맨 꼭대기까지 계속 됩니다. - 연쇄의 꼭대기에서 마지막 클래스는 모든 저장속성이 값을 가졌는지 확인하고, 인스턴스의 메모리는 완전히 초기화 되었습니다. 첫 단계를 종료합니다.
  • #22 연쇄의 꼭대기에서 거꾸로 내려오면서 각각의 지정 초기자는 해당 클래스 인스턴스를 수정 할 수 있습니다. 초기자들은 이제 self에 접근하고, 프로퍼티를 수정 할 수 있습니다. 인스턴스 메소드도 호출 할 수 있습니다. - 끝으로, 모든 편의 초기자들은 해당 클래스 인스턴스를 수정 할 수 있고, self를 사용 할 수 있습니다.
  • #23  이런 접근 방식은 더 복잡한 자식 클래스가 부모 클래스의 단순한 초기자를 자동으로 상속받아서 불완전하게 초기화되는 것을 막아줍니다.
  • #24  아마도 초기화 도중에 클래스의 무엇인가를 수정 하고 싶을 때, 수정한 자식 클래스가 부모로 부터 초기자를 상속 받기를 원할 것 입니다. 이 때는 수정한 자식 클래스에 같은 초기자를 오버라이딩해서 구현 할 수 있습니다. 지정 초기자를 오버라이딩 한다면, 자식 클래스에서 구현체를 오버라이드 할 수 있고, 오버라이딩한 버전에서 부모 클래스 버전의 초기자를 호출 할 수 있습니다. 편의 초기자를 오버라이딩 하고싶으면, 오버라이드한 초기자는 반드시 자식클래스 안의 지정 초기자를 호출해야 합니다.
  • #25 부모클래스의 모든 편의 초기자를 자동으로 상속한다. (Rule 1에 따라 지정 초기자를 상속 받아서 구현 하든가, 자식 클래스 정의의 일부로서 구현 할 수 있다.) 조건을 만족하면 자식 클래스가 자동으로 부모 클래스의 초기자를 상속 받습니다. 여기 진짜 말이긴데, 결국 자식 클래스가 부모 클래스의 모든 초기자를 구현해야 한다는 말이다.
  • #27 클래스는 기본 멤버 단위 초기자가 없습니다. 그래서 Food 클래스는 단일 인자 name을 받는 초기자를 제공합니다. Food 클래스는 편의 초기자도 제공합니다.
  • #29 RecipeIngredient 클래스에는 한 개의 지정 초기자 init(name:String, quantity: Int)가 있습니다. 이 초기자는 RecipeIngredient 인스턴스의 모든 프로퍼티를 채우는데 쓰입니다. 이 초기자는 RecipeIngredient에서 새롭게 추가된 quantity에 값을 전달하면서 시작 합니다. 그리고나서, 이 초기자는 Food 클래스의 init(name:String)를 초기자를 대신 실행 합니다. 1단계는 해당 클래스가 가지는 저장속성에 초기값을 할당 한다. 입니다. 이 프로세스는 두 단계 초기화에서 1단계를 만족합니다.
  • #30 RecipeIngredient는 init(name:String)도 정의 하고 있다. 이 편리 초기자는 별다른 입력이 없는 모든 RecipeIngredient의 quantity를 1로 가정 했다. 이 편의 초기자는 단순히 클래스의 지정 초기자를 대리한다.
  • #31  RecipeIngredient의 init(name:String) 편의 초기자가 Food의 초기자 init(name:String)과 같은 파라메터를 받습니다. RecipeIngredient가 이 초기자를 편의 초기자로 제공하지만, RecipeIngredient는 모든 부모 클래스의 지정 초기자들을 구현한것이 된다. 그러므로, RecipeIngredient는 자동으로 모든 부모 클래스의 편의 초기자들을 상속받는다.
  • #32 이 예제에서 RecipeIngredient의 부모클래스 Food는 하나의 편의 초기자 init()을 제공 합니다. 따라서 이 초기자는 RecipeIngredient에 상속 됩니다. init()의 상속된 버전은 Food 버전과 똑같이 기능 합니다. 대리 수행하는 초기자 init(name:String)을 Food 버전이 아니라 ReceipeIngredient 버전을 사용 한다는 것만 빼면요.
  • #33 이 클래스가 도입한 모든 속성의 초기값을 제공하고, 어떤 이니셜라이저도 스스로 정의하지 않기 때문에 ShoppingListItem은 자동적으로 모든 지정 이니셜라이저와 편의 이니셜라이저를 부모 클래스에서 상속받습니다.
  • #34 중괄호 바로 옆에 빈 괄호 한쌍이 있는 것은 클로저를 즉시 실행 하도록 한다. 이 괄호가 없으면 값이 아니라 클로저 자체를 속성에 할당 하려고 시도 하는 것이 된다. 알아야 할 점은 클로저가 호출되는 시점은 인스턴스의 나머지는 아직 초기화 되지 않은 상태이다. 따라서 self를 쓰거나 다른 메소드를 호출 할 수 없다.
  • #35 중괄호 바로 옆에 빈 괄호 한쌍이 있는 것은 클로저를 즉시 실행 하도록 한다. 이 괄호가 없으면 값이 아니라 클로저 자체를 속성에 할당 하려고 시도 하는 것이 된다. 알아야 할 점은 클로저가 호출되는 시점은 인스턴스의 나머지는 아직 초기화 되지 않은 상태이다. 따라서 self를 쓰거나 다른 메소드를 호출 할 수 없다.