728x90
초기화
- 클래스, 구조체, 열거형 인스턴스를 사용하기 위해 준비 작업을 하는 단계
- 각 저장 프로퍼티의 초기 값을 설정
- 초기화 과정은 initializer를 정의 하는 것으로 구현
- Swift initializer는 값을 반환 ❌
- 초기화와 반대로 여러 값과 자원의 해지를 위해 deinitializer도 사용
저장 프로퍼티를 위한 초기값 설정(Setting initial Values for Stored Properties)
- 인스턴스의 저장 프로퍼티는 사용하기 전에 반드시 특정 값으로 초기화
- 기본값으로 설정할 수 있고, 특정 값을 설정할 수도 있음
- initializer에서 저장 프로퍼티에 값을 직접 설정하면 프로퍼티 옵저버가 호출되지 않고 값 할당이 수행
이니셜라이저 (Initializers)
- 이니셜라이저는 특정 타입의 인스턴스를 생성, 이니셜라이저의 가장 간단한 형태는 파라미터가 없고 init 키워드 사용
- init () { }
struct Bulmang {
var weight: Double
init() {
weight = 66.7
}
}
var bulmang = Bulmang()
print("불망의 몸무게는 \\(bulmang.weight)")
기본 프로퍼티 (Default Property Values)
- 프로퍼티의 선언과 동시에 값을 할당하면 그 값을 초기값으로 사용
- 항상 같은 초기 값을 갖는다면 기본 프로퍼티를 사용하는 것이 좋음, 프로퍼티에 타입을 선언하지 않아도 컴파일러는 타입추론을 함
// 프로퍼티를 선언과 동시에 초기 값을 할당
struct Bulmang {
var weight = 66.7
}
var bulmang = Bulmang()
print("불망의 몸무게는 \\(bulmang.weight)")
커스터마이징 초기화(Customizing Initialization)
- 초기화 프로세스를 입력 값과 옵셔널 프로퍼티 타입 혹은 상수 값을 할당해서 커스터마이징
초기화 파라미터(Initialzation Parameters)
- 초기화 정의에 파라미터를 정의해 사용할 수 있음
struct Celsius {
var temperatureInCelsius: Double
init(fromFahrenheit fahrenheit: Double) {
temperatureInCelsius = (fahrenheit - 32.0) / 1.8
}
init(fromKelvin kelvin: Double) {
temperatureInCelsius = kelvin - 273.15
}
}
let boilingPointOfWater = Celsius(fromFahrenheit: 212.0)
// boilingPointOfWater.temperatureInCelsius is 100.0
let freezingPointOfWater = Celsius(fromKelvin: 273.15)
// freezingPointOfWater.temperatureInCelsius is 0.0
파라미터 이름과 인자 레이블 (Parameter Names and Argument Labels)
- 메소드 파라미터와 초기화 파라미터 모두 파라미터 이름과 인자 레이블을 갖지만,이니셜라이저는 특정 메소드에서 지정하는 메소드 이름을 지정하지 않고 이니셜라이저 식별자로 파라미터를 사용
- 모든 파라미터는 인자 레이블을 갖는데 만약 사용자가 이 레이블을 지정하지 않느면 Swift가 자동으로 하나를 할당
struct Color {
let red, green, blue: Double
init(red: Double, green: Double, blue: Double) {
self.red = red
self.green = green
self.blue = blue
}
init(white: Double) {
red = white
green = white
blue = white
}
}
// 두 초기화 구문 모두 각 초기화 구문 파라미터에 값을 제공하여 새로운 Color 인스턴스를 생성
let magenta = Color(red: 1.0, green: 0.0, blue: 1.0)
let halfGray = Color(white: 0.5)
// 인수 라벨을 사용하지 않고 초기화 구문을 호출할 수 없습니다. 인수 라벨은 정의 되었다면 항상 사용되어야 하고 생략 시 컴파일 시 에러가 발생
let veryGreen = Color(0.0, 1.0, 0.0)
// this reports a compile-time error - argument labels are required
// 초기화 구문 파라미터에 인수 라벨 사용을 원치 않을 경우 명시적으로 인수 라벨 대신에 언더바 (_)를 작성하여 기본 동작을 재정의
struct Celsius {
var temperatureInCelsius: Double
init(fromFahrenheit fahrenheit: Double) {
temperatureInCelsius = (fahrenheit - 32.0) / 1.8
}
init(fromKelvin kelvin: Double) {
temperatureInCelsius = kelvin - 273.15
}
init(_ celsius: Double) {
temperatureInCelsius = celsius
}
}
let bodyTemperature = Celsius(37.0)
// bodyTemperature.temperatureInCelsius is 37.0
// 초기화 구문 호출 Celsius(37.0) 은 인수 라벨이 필요치 않다는 의도가 명확합니다. 따라서 초기화 구문을 init(_ celsius: Double) 로 작성하여 이름없는 Double 값을 제공하여 호출
옵셔널 프로퍼티 타입(Optional Property Types)
- 사용자 타입이 초기화 동안 값을 설정할 수 없거나 추후에 "값 없음"을 가질 수 있기 때문에 논리적으로 "값 없음"을 가질 수 있는 하나의 저장된 프로퍼티를 가지고 있다면 옵셔널 타입으로 프로퍼티를 선언
- 자동적으로 초기화 동안 "아직 값 없음"을 가진다는 의도를 위해 nil 의 값으로 초기화
class SurveyQuestion {
var text: String
var response: String?
init(text: String) {
self.text = text
}
func ask() {
print(text)
}
}
let cheeseQuestion = SurveyQuestion(text: "Do you like cheese?")
cheeseQuestion.ask()
// Prints "Do you like cheese?"
cheeseQuestion.response = "Yes, I do like cheese."
// 응답은 질문 되기 전까지 알수없어서 response 프로퍼티는 String? 타입또는 옵셔널 String타입으로 선언
// 새로운 인스턴스 SurveyQuestion이 초기활 될 때 nil이 자동으로 할당
초기화 동안 프로퍼티 상수 할당(Assigning Constant During Initialization)
- 초기화가 완료될 때까지 한정된 값으로 설정되는 한 초기화 중 언제든지 프로퍼티 상수에 값을 할당할 수 있음
- 프로퍼티 상수에 값이 할당되면 더 이상 수정 불가.
// text 프로퍼티는 프로퍼티 변수보다 프로퍼티 상수로 사용하기 위해 위의 SurveyQuestion 예제를 수정가능
// text 프로퍼티는 현재 상수이지만 여전히 클래스의 초기화 구문 내에서 설정할 수 있음
class SurveyQuestion {
let text: String
var response: String?
init(text: String) {
self.text = text
}
func ask() {
print(text)
}
}
let beetsQuestion = SurveyQuestion(text: "How about beets?")
beetsQuestion.ask()
// Prints "How about beets?"
beetsQuestion.response = "I also like beets. (But not with cheese.)"
기본 초기화 구문(Default Initializers)
- Swift는 모든 프로퍼티에 대한 기본값을 제공하고 적어도 하나의 초기화 구문을 제공하지 않는 모든 구조체 또는 클래스에 대해 기본 초기화 구문을 제공
- 모든 프로퍼티가 기본값으로 설정된 새로운 인스턴스를 생성
// 쇼핑 리스트에 있는 항목의 이름, 수량, 그리고 구매 상태를 캡슐화하는 ShoppingListItem 이라는 클래스를 정의
class ShoppingListItem {
var name: String?
var quantity = 1
var purchased = false
}
var item = ShoppingListItem()
// 쇼핑리스트아이템클래스의 모든 프로퍼티는 기본값을 가지고 있고 상위 클래스가 없는 기본클래스타입
// 자동적으로 모든 프로퍼티를 기본값으로 설정한 새로운 인스턴스를 생성하는 기본 초기화 구문 구현
// ShoppingListItem() 클래스에 기본 초기화 구문 사용, item이라는 변수에 인스턴스 할당
구조체 타입에 대한 멤버별 초기화 구문(Memberwise Initializers for Structure Types)
- 구조체 타입은 자신의 초기화 구문을 정의하지 않으면 자동적으로 멤버별 초기화 구문을 받음
- 구조체는 기본값을 가지지 않은 저장된 프로퍼티라도 멤버별 초기화 구문을 받음
- 새로운 구조체 인스턴스에 멤버 프로퍼티를 초기화 하기 위한 짧은 구문 방법
- 새로운 인스턴스의 프로퍼티를 위한 초기화 값은 이름으로 멤버별 초기화 구문으로 전달
// width, height라는 2개의 프로퍼티를 가지는 Size 구조체 정의
// 두 프로퍼티 모두 0.0 의 기본값이 할당되어 Double 타입으로 추론
struct Size {
var width = 0.0, height = 0.0
}
let twoByTwo = Size(width: 2.0, height: 2.0)
값 타입을 위한 초기화 구문 위임(Initializer Delegation for Value Types)
- 초기화 구문은 인스턴스의 초기화 부분을 수행하기 위해 다른 초기화 구문을 호출
- 여러 초기화 구문에서 코드가 중복되는 것을 방지
- 구조체와 같은 값 타입에서 초기화 과정에 사용
- 초기화 메소드 간에 코드 중복을 최소화 시켜 가독성과 유지보수성이 높아짐
- init 키워드를 사용하여 초기화 메소드를 정의
- 다른 초기화 메소드를 호출할 때 self.init 형태 사용
- 값 타입에 대해 사용자 화 초기화 구문을 정의한다면 그 타입에 대해 기본 초기화 구문 또는 구조체의 경우 멤버별 초기화 구문에 더이상 접근할 수 없음
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)
}
}
// 구조체를 수신했을 때 기본 초기화 구문과 기능적으로 동일
let basicRect = Rect()
// basicRect's origin is (0.0, 0.0) and its size is (0.0, 0.0)
// origin과 size 인수값을 적절한 저장된 프로퍼티에 할당
let originRect = Rect(origin: Point(x: 2.0, y: 2.0),size: Size(width: 5.0, height: 5.0))
// originRect's origin is (2.0, 2.0) and its size is (5.0, 5.0)
// center 점과 size 값을 기반으로 적절한 원점을 계산하는 것을 시작하고 다음 적절한 프로퍼티로 새로운 원점과 크기를 저장하는 init(origin:size:) 초기화 구문을 호출
let centerRect = Rect(center: Point(x: 4.0, y: 4.0),size: Size(width: 3.0, height: 3.0))
// centerRect's origin is (2.5, 2.5) and its size is (3.0, 3.0)
클래스 상속과 초기화 (Class Inheritance and Initialization)
- 상위 클래스로 부터 상속한 클래스의 모든 프로퍼티를 포함하는 모든 클래스의 저장된 프로퍼티는 초기화중에 반드시 초기값이 할당해야 됨
지정된 초기화 구문과 편의 초기화 구문(Designated Initializers and Convenience Initializers)
- 클래스에 주 초기화 구문, 지정된 초기화 구문은 해당 클래스에 의해 도입된 모든 프로퍼티를 완벽하게 초기화하고 적절한 상위 클래스 초기화를 호출하여 상위 클래스 체인까지 초기화 프로세스를 계속 진행
- 모든 클래스에는 최소 하나의 지정된 초기화 구문이 있어야함
- 경우에 따라 자동 초기화 구문 상속(Automatic Initializer Inheritance)에서 설명하듯이 상위 클래스에서 하나 이상의 지정된 초기화 구문을 상속하는 것으로 충족
- 편의 초기화 구문(Convenience initializers)
- 클래스에 대해 초기화 구문을 지원하는 보조 초기화 구문
- 지정된 초기화 구문의 파라미터를 기본값으로 설정하여 편의 초기화 구문과 동일한 클래스에서 지정된 초기화 구문을 호출하도록 편의 초기화 구문을 정의
- 특정 사용 케이스 또는 입력 값 타입에 대한 해당 클래스의 인스턴스를 생성하기 위해 편의 초기화 구문을 정의
- 클래스에 필요하지 않은 경우 편의 초기화 구문(Convenience initializers)을 제공할 필요가 없음
- 일반적인 초기화 패턴에 대한 바로가기가 시간을 절약하거나 클래스 초기화를 더 명확하게 만들 때마다 편리한 초기화 구문을 만듬
class Person {
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
convenience init(name: String) {
self.init(name: name, age: 0)
}
}
모르는 용어
Superclass Chain
- OOP에서 상속관계를 형성하는 class간의 관계를 나타냄
- 하위 class가 상위 class부터 상속받은 method, property, 초기화 메서드등 사용
- 코드의 재사용성과 유지보수성이 높아지고 상위클래스체인(Superclass Chain)을 이해하면 오류수정하거나 디버깅할 때 도움이 됨
728x90
'기타 > Today I Learned' 카테고리의 다른 글
[TIL] Swift 문법 옵셔널 체이닝(Optional Chaining) (1) | 2023.05.17 |
---|---|
[TIL] Swift 문법 초기화(Initializer) - 2 (0) | 2023.05.11 |
[TIL] Swift 문법 상속(Inheritance) (0) | 2023.05.05 |
[TIL] Swift 문법(Subscripts) (0) | 2023.05.03 |
[TIL] Swift 문법 메소드(Methods) (0) | 2023.04.28 |