이니셜라이저 예제
아직 다루지 않은 이니셜라이저 관련 내용인데 몰랐던 내용을 예제와 함께 간단히 써볼게요.
init 사용 및 고차함수 관련 내용입니다. 신기방기합니다.
문법은 다음기회에... 정리해서 올릴게요
오늘부터 저는 커피 장사를 하고 있습니다.
일단 장사를 하기 앞서 커피 메뉴판을 만들어 줬어요.
struct Menu {
let coffee: String
let size: String
}
메뉴도 만들었으니 손님 이름과 함께 주문을 받아야겠죠?
struct CoffeeOrder {
let name: String
let order: Menu
}
그런데 갑자기 손님이 들이닥쳐서 많은 주문을 처리하기 힘들어서
한눈에 보기 위해 주문 리스트도 만들어 줬어요.
struct CoffeeOrderList {
let orderList: [CoffeeOrder]
}
벌써 사람들이 메뉴를 고르고 줄을 서있네요.
빨리 주문을 받아 봅시다.
let daniel: Menu = Menu(coffee: "cappuccino", size: "small")
let basco: Menu = Menu(coffee: "espresso", size: "medium")
let nina: Menu = Menu(coffee: "latte", size: "large")
자 주문을 받기 위해 CoffeeOrder로 생성자를 만들어주겠습니다.
여기서 유심히 봐야 하는 게 실행인 소괄호를 "()" 하지 않으면 클로저 타입이라는 겁니다!
생성해 준 CoffeeOrder.init의 타입이 클로저로 만들어져 있네요. (Sting, Menu) -> CoffeeOrder
let order: (String, Menu) -> CoffeeOrder = CoffeeOrder.init
클로저에 직접 값을 주거나 구조체의 기본 생성자에 값을 주거나 직접 생성자를 만들어 주거나 등등...
이와 같이 여러 방식으로 CoffeeOrder의 초기화(init)가 가능합니다!
let order1: CoffeeOrder = order("Daniel", daniel)
let order2: CoffeeOrder = CoffeeOrder(name: "Basco", order: basco)
let order3: CoffeeOrder = CoffeeOrder.init(name: "Nina", order: nina)
이렇게 커피 주문 리스트를 만들어 한눈에 볼 수 있게 됐네요!
let orders: [CoffeeOrder] = [order1, order2, order3]
// 주문 리스트 완성!
let ordersList = CoffeeOrderList(orderList: orders)
이번엔 고차함수(map)를 이용해 정리해 봅시다.
map을 사용하기 위해 튜플로 코드를 조금 변경하겠습니다.
다시 사람들이 기다리고 있습니다.
let daniel: (String ,Menu) = ("Daniel", Menu(coffee: "cappuccino", size: "small"))
let basco: (String ,Menu) = ("Basco", Menu(coffee: "espresso", size: "medium"))
let nina: (String ,Menu) = ("Nina", Menu(coffee: "latte", size: "large"))
이번에는 사람들이 이름만 적고 주문 메뉴를 뭉터기로 던지고 가는 바람에
빠르게 주문을 정리해야 하는 상황입니다.
let customers: [(String, Menu)] = [daniel, basco, nina]
빠르게 정리하기 위해서 map을 사용해 볼까요?
고차함수 map을 사용하기 앞서 일단 map의 선언부터 살짝 보고 갈게요.
func map<T>(_ transform: (Self.Element) throws -> T) rethrows -> [T]
Self.Element는 각각의 요소를 나타내고 어떤 과정을 거쳐 정해지지 않은 타입(제너릭 타입)으로 리턴하네요.
만약 배열(customers)에서 map을 사용한다면, 각각의 요소는 daniel, basco, nina를 나타내고
과정을 거쳐 그 결과를 배열로 묶어서 나타내겠죠?
그리고 실패가 없다고 생각하면 이런 식으로 타입이 정해지겠네요.
func map(_ transform: (String ,Menu) -> T) -> [T]
사용하기 전에 복습을 해봅시다.
아까 위의 설명에서 이니셜라이저에 소괄호를 붙이지 않으면 어떻게 된다고 했을까요?
클로저 타입으로 된다고 말씀드렸죠!?!
(String, Menu) -> CoffeeOrder
let order: (String, Menu) -> CoffeeOrder = CoffeeOrder.init
바로 map을 사용해 봅시다.
let orders: [CoffeeOrder] = customers.map(CoffeeOrder.init)
// 주문 리스트 완성
let ordersList = CoffeeOrderList(orderList: orders)
그런데 왜 이렇게 변하지? 간단하게 설명을 해드리겠습니다.
// customers를 map으로 변환할 때 요소
daniel, basco, nina
// daniel, basco, nina의 타입
(String, Menu)
// map은 각각의 요소들을 파라미터에 하나하나 대입하여 작업 합니다
customers.map(CoffeeOrder.init)
// CoffeeOrder.init의 타입 (클로저)
(String, Menu) -> CoffeeOrder
// 요소의 타입과 클로저의 파라미터가 일치
// 요소를 대입하게 되면 클로저가 실행되서 CoffeeOrder를 리턴
daniel -> CoffeeOrder
basco -> CoffeeOrder
nina -> CoffeeOrder
// 순차적으로 작업을 실행 후 묶어서 배열로 리턴
[daniel -> CoffeeOrder, basco -> CoffeeOrder, nina -> CoffeeOrder]
// 결과값
[CoffeeOrder(daniel), CoffeeOrder(basco), CoffeeOrder(nina)]
설명이 허접하지만 이해되셨길 바라며... 여기까지가 제가 설명할 수 있는 한계입니다...
기존에는 고차함수 사용 시 클로저를 통해 아래와 같이 인수($0, $1)만을 사용했었는데, 위와 같은 방식도 있네요!
let orders: [CoffeeOrder] = customers.map({CoffeeOrder(name: $0, order: $1)})
코드도 깔끔해진 거 같고 신기 방기합니다~! 🫠
부족한 설명이지만, 조금은 이해 가셨나요?
틀린 내용이 있다면 언제든지 지적해 주시면 감사히 받겠습니다. 🫠
읽어주셔서 감사합니다 😃
'Xcode > Swift 문법' 카테고리의 다른 글
[iOS/Swift] URL, URLComponents 빠개기 (0) | 2023.02.11 |
---|---|
[iOS/Swift] 프로토콜 CaseIterable (열거형에서 모든 case를 배열로 다루기) (2) | 2023.02.09 |
[iOS/Swift] 동시성(Concurrency) 프로그래밍 (0) | 2023.02.04 |
[iOS/Swift] 형 변환 (Type Casting) (0) | 2023.01.31 |
[iOS/Swift] AsyncStream / AsyncThrowingStream (0) | 2023.01.26 |