Danny의 iOS 컨닝페이퍼
article thumbnail

이니셜라이저 예제

아직 다루지 않은 이니셜라이저 관련 내용인데 몰랐던 내용을 예제와 함께 간단히 써볼게요.

 

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)})

 

코드도 깔끔해진 거 같고 신기 방기합니다~! 🫠

 

 

부족한 설명이지만, 조금은 이해 가셨나요?

틀린 내용이 있다면 언제든지 지적해 주시면 감사히 받겠습니다. 🫠
읽어주셔서 감사합니다 😃

 

 

반응형
profile

Danny의 iOS 컨닝페이퍼

@Danny's iOS

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!