케이스가 선택가능한(한정됨) 가짓 수로 정해져 있을때 정의
열거형을 사용하면 코드의 가독성과 안정성이 높아짐 ===> 명확한 분기 처리 가능
enum Weekday {
case monday
case tuesday
case sunday
}
enum CompassPoint {
case north, south, east, west
}
// 열거형 타입으로 선언하면 열거형의 요소를 담을 수 있다
var today: Weekday = Weekday.monday
today = .tuesday
// 일요일인 경우만 특정한 처리를 하고 싶을때
if today == .sunday {
}
// 모든 각각의 경우를 처리하고 싶을때
if today == .monday {
print("오늘은 월요일입니다.")
} else if today == .tuesday {
print("오늘은 화요일입니다.")
} else {
print("오늘은 일요일입니다.")
}
switch today {
case .monday: // today == .mondey이면
print("오늘은 월요일입니다.")
case .tuesday:
print("오늘은 화요일입니다.")
case .sunday:
print("오늘은 일요일입니다.")
}
// 여러가지 형태로 원시값을 정의 가능
// (Hashable한 - Int / String / Character / Double 등 가능)
// 원시값의 타입을 Int로 하면
// 원시값 입력안하면 0, 1, 2 이렇게 자동으로 저장됨
// 정수의 경우 숫자가 하나씩 증가
// 1(설정시), 2, 3
// 0, 2(설정시), 3
enum Alignment: Int {
case left = 0
case center
case right
}
enum Alignment1: String {
case left = "L"
case center = "C"
case right = "R"
}
// 인스턴스 생성시 - 옵셔널타입으로 리턴 (실패가능)
// ✅**rawValue가 없을수도 있기 때문에**✅
let align = Alignment(rawValue: 0)
// 접근연산자를 통해 원시값 자체에도 접근가능
let leftValue = Alignment.center.rawValue
// (가능하지만) 문자열 방식으로는 잘 사용하지는 않음
let center = Alignment1(rawValue: "C") // center
let centerValue = Alignment1.center.rawValue
enum Computer {
case cpu(core: Int, ghz: Double)
case ram(Int, String)
case hardDisk(gb: Int)
}
// 각 케이스별로 상이한 특징이 있고, 그것을 저장 / 활용할 필요가 있을 때
// 개별케이스마다 저장할 형식을 따로 정의(자료형에 제한이 없음 / 튜플의 형태)
// 하나의 케이스에 서로다른 연관값을 저장할 수 있음 ===> 선언시점이 아니라, 새로운 열거형 값을 생성할때 저장
let myChip1 = Computer.cpu(core: 8, ghz: 3.5)
let myChip3 = Computer.ram(16, "DRAM")
let myChip6 = Computer.hardDisk(gb: 128)
var chip = Computer.cpu(core: 8, ghz: 2.0)
// 일치하는 경우에 return하기
switch chip {
case .cpu(core: 8, ghz: 3.1):
print("CPU 8코어 3.1GHz입니다.")
case .cpu(core: 8, ghz: 2.6):
print("CPU 8코어 2.6GHz입니다.")
// _의 의미는 어떤거든 상관이 없다는뜻(와일드카드패턴)
case .ram(32, _):
print("32기가램 입니다.")
default:
print("그 이외의 칩에는 관심이 없습니다.")
}
// 특정case를 알맞게 return하기
switch chip {
// let core = 연관값, let ghz = 연관값
case let .cpu(core, ghz):
print("CPU \(core)코어 \(ghz)GHz입니다.")
case let .ram(a, _):
print("램 \(a)기가램 입니다.")
case let .hardDisk(a) :
print("하드디스크 \(a)기가 용량입니다.")
}
연관값이 있는 옵셔널타입
enum Optional<Wrapped> {
case some(Wrapped)
case none
}
var num: Int? = 7
== Optional.some(7)
== .some(7)
switch num {
// 열거형 case 패턴을 활용해서, 내부 연관값을 꺼냄
// let a = 7 a에다가 7을 넣을 수 있다면 즉, nil이 아니면
case let .some(a):
print(a)
case .none:
print("nil")
}
// 로그인 타입을 정의
// rawValue를 String으로 선언후 아무것도 대입하지 않으면 case그대로
enum LoginProvider: String {
case email
// case email = "email"
case facebook
// case facebook = "facebook"
case google
// case google = "google"
}
let userLogin = LoginProvider.facebook
// 열거형은 한정된 사례로 만든 타입이고,
// 스위치문은 표현식에 대한 분기처리에 최적화
switch userLogin {
case .email:
print("이메일 로그인")
case .facebook:
print("페이스북 로그인")
case .google:
print("구글 로그인")
}
// 물론 특정한 경우도 처리 가능
if LoginProvider.email == userLogin {
print("이메일 로그인")
}
enum SomeEnum {
case left
case right
}
// 타입을 다시 옵셔널 열거형으로 선언
let x: SomeEnum? = .left
💡 [SomeEnum?의 의미] 옵셔널 열거형
switch x {
// ✅Optional.some(let value) = Optional.some(SomeEnum.left)
case .some(let value):
switch value {
case .left:
print("왼쪽으로 돌기")
case .right:
print("오른쪽으로 돌기")
}
case .none:
print("계속 전진")
}
// ✅편의적 기능 제공
// switch문에서 옵셔널 열거형 타입을 사용할때, 벗기지 않아도 내부값 접근가능
switch x {
case .left:
print("왼쪽으로 돌기")
case .right:
print("오른쪽으로 돌기")
// case .none도 가능
case nil:
print("계속 전진")
}
// .hardDisk의 gB를 print하고 싶은데 이Case를 위해 switch문 작성...
switch chip {
case Computer.hardDisk(gb: let gB): // let gB = 연관값
print("\(gB)기가 바이트 하드디스크임")
default:
break
}
// if문으로 특정 case만 처리할 수 있음
if case Computer.hardDisk(gb: let gB) = chip {
print("\(gB)기가 바이트 하드디스크임")
}
// if 조건문에서 ","의 경우 &&를 의미함
if case let Computer.hardDisk(gb: gB) = chip, gB == 256 {
print("256기가 바이트 하드디스크임")
}
let chiplists: [Computer?] = [
nil,
.cpu(core: 4, ghz: 3.0),
.cpu(core: 8, ghz: 3.5),
.ram(16, "SRAM"),
.ram(32, "DRAM"),
.cpu(core: 8, ghz: 3.5),
.hardDisk(gb: 500),
.hardDisk(gb: 256)
]
// 배열중에서 특정 케이스만 뽑아서 활용 가능 ⭐️
// 값이존재하는지 안하는지를 보는게아니라 .some을 쓰지 않음
for case .cpu(core: let c, ghz: let h) in chiplists {
print("CPU칩: \(c)코어, \(h)헤르츠")
}
// 옵셔널 타입을 포함하는 배열에서 반복문을 사용하는 경우
let arrays: [Int?] = [nil, 2, 3, nil, 5]
// .some은 내부에 값이 있는 경우임 즉, 내부에 값이 있는것만 print하겟다는 의미
// optional에서 enum은 .some과 .none 두가지임
for case .some(let number) in arrays {
print("Found a \(number)")
}
let a: Int? = 1
// 1) 열거형 케이스 패턴
switch a {
case .some(let z):
print(z)
case .none: // nil이라고 써도됨
print("nil")
}
// 2) 옵셔널 패턴
switch a {
case let z?: // .some을 조금 더 간소화하는 문법
print(z)
case nil: // .none 이라고 써도됨
print("nil")
}
// 특정 사례만 다루는 (if문)
// 1) 열거형 케이스 패턴
if case .some(let x) = num {
print(x)
}
// 2) 옵셔널 패턴 (.some을 ? 물음표로 대체 가능한 패턴)
if case let x? = num {
print(x)
}
let arrays: [Int?] = [nil, 2, 3, nil, 5]
//특정케이스만 for 문을 돌리는 방법
// 1) 열거형 케이스 패턴
// 연관값이존재하는경우다(optional의 경우)
for case .some(let number) in arrays {
print("Found a \(number)")
}
// 2) 옵셔널 패턴
for case let number? in arrays {
print("Found a \(number)")
}
연관값이 없고 열거형이 옵셔널로 선언되어있는경우
→ 두번 벗길필요가 없다(.some을 바인딩해서 그안에서 .left .right할필요X)
연관값이 있는경우 모든케이스를 다루고 싶지 않은 경우 조건문반복문에 case를 바인딩
표현식이 옵셔널 타입인 경우 - 옵셔널 패턴(.some대신 ?)
→ let a: Int? = 1 ⇒ 이경우가 표현식이 옵셔널인 경우이다