let num1: Int = 123
let num2: Int = 456
num1 == num2
num1 != num2
let str1: String = "Hello"
let str2: String = "안녕"
str1 == str2
str1 != str2
[Int의 내부 구현]
@frozen public struct Int : FixedWidthInteger, SignedInteger {
...
public static func == (lhs: Int, rhs: Int) -> Bool
...
}
➡︎ 비교연산자(==)메서드 자동구현
enum SuperComputer: Equatable {
case cpu(core: Int, ghz: Double)
case ram(Int)
case hardDisk(gb: Int)
}
SuperComputer.cpu(core: 8, ghz: 3.5) == SuperComputer.cpu(core: 16, ghz: 3.5)
SuperComputer.cpu(core: 8, ghz: 3.5) != SuperComputer.cpu(core: 8, ghz: 3.5)
enum Direction {
case east
case west
case south
case north
}
Direction.north == Direction.east // false
Direction.north != Direction.east // true
struct Dog {
var name: String
var age: Int
}
extension Dog: Equatable {}
// 이렇게 전체 구현할 필요 없음
//extension Dog: Equatable {
// static func ==(lhs: Dog, rhs: Dog) -> Bool {
// return lhs.name == rhs.name && lhs.age == rhs.age
// }
//}
let dog1: Dog = Dog(name: "초코", age: 10)
let dog2: Dog = Dog(name: "보리", age: 2)
dog1 == dog2
dog1 != dog2
class Person {
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
// 비교하고 싶어서, Equatable 프로토콜 채택 ====> 클래스에서는 에러 발생 ===> 비교연산자(==)를 구현 직접구현해야함
extension Person: Equatable {
static func ==(lhs: Person, rhs: Person) -> Bool { // 특별한 이유가 없다면 모든 속성에 대해, 비교 구현
return lhs.name == rhs.name && lhs.age == rhs.age
//return lhs.name == rhs.name // 이름만 같아도 동일하다고 보려면 이렇게 구현
//return lhs.age == lhs.age // 나이만 같아도 동일하다고 보려면 이렇게 구현
}
}
let person1: Person = Person(name: "홍길동", age: 20)
let person2: Person = Person(name: "임꺽정", age: 20)
person1 == person2
person1 != person2
let num1: Int = 123
let num2: Int = 456
num1 < num2
num1 > num2
let str1: String = "Hello"
let str2: String = "안녕"
str1 < str2
str1 > str2
[Int의 내부 구현]
@frozen public struct Int : FixedWidthInteger, SignedInteger {
...
public static func < (lhs: Int, rhs: Int) -> Bool
...
}
enum Direction: Int {
case east
case west
case south
case north
}
extension Direction: Comparable { //Type 'Direction' does not conform to protocol 'Comparable'
static func < (lhs: Direction, rhs: Direction) -> Bool {
return lhs.rawValue < rhs.rawValue
}
}
Direction.north < Direction.east // false
Direction.north > Direction.east // true
enum SuperComputer: Comparable {
case cpu(core: Int, ghz: Double)
case ram(Int)
case hardDisk(gb: Int)
}
SuperComputer.cpu(core: 8, ghz: 3.5) < SuperComputer.cpu(core: 16, ghz: 3.5) // true
SuperComputer.cpu(core: 8, ghz: 3.5) > SuperComputer.cpu(core: 8, ghz: 3.5) // false
enum MyDirection: Comparable {
case east
case west
case south
case north
}
MyDirection.north < MyDirection.east // false
MyDirection.north > MyDirection.east // true
struct Dog {
var name: String
var age: Int
}
extension Dog: Comparable { // 이름순으로 갈것인지 / 나이순으로 갈 것인지 구현해야함
// static func ==(lhs: Dog, rhs: Dog) -> Bool { // Equatable은 name, age의 저장 속성이 Equatable프로토콜을 구현하기에 자동제공
// return lhs.name == rhs.name && lhs.age == rhs.age
// }
static func < (lhs: Dog, rhs: Dog) -> Bool {
return lhs.age < rhs.age
}
}
let dog1: Dog = Dog(name: "초코", age: 10)
let dog2: Dog = Dog(name: "보리", age: 2)
dog1 < dog2
dog1 > dog2
class Person {
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
extension Person: Comparable {
// 클래스의 경우, ==연산자도 구현해야함
static func ==(lhs: Person, rhs: Person) -> Bool {
return lhs.name == rhs.name && lhs.age == rhs.age
}
// 나이순으로 정렬하고자 함 ⭐️
static func < (lhs: Person, rhs: Person) -> Bool {
return lhs.age < rhs.age
}
}
let person1: Person = Person(name: "홍길동", age: 20)
let person2: Person = Person(name: "임꺽정", age: 22)
person1 < person2
person1 > person2
let num1: Int = 123
let num2: Int = 456
let set: Set = [num1, num2]
// Int가 해셔블하기 때문에, Set의 원소가 될 수 있음
let str1: String = "Hello"
let str2: String = "안녕"
let set2: Set = [str1, str2]
// String이 해셔블하기 때문에, Set의 원소가 될 수 있음
//123.hashValue // ===> 이 방식은 현재 deprecated되었음(앞으로 사용못하게될 예정)
/**=============================================================
[Int의 내부 구현]
extension Int : Hashable {
@inlinable public func hash(into hasher: inout Hasher)
public var hashValue: Int { get }
}
enum SuperComputer: Hashable {
case cpu(core: Int, ghz: Double)
case ram(Int)
case hardDisk(gb: Int)
}
let superSet: Set = [SuperComputer.cpu(core: 8, ghz: 3.5), SuperComputer.cpu(core: 16, ghz: 3.5)]
// 예외-2) 연관값이 없다면(원시값 여부는 상관없음) Hashable 프로토콜을 채택하지 않아도 유일성 판별 가능
// ===> 기본적으로 추가정보가 없다면 유일성 판별 가능하다는 논리 ⭐️
enum Direction {
case east
case west
case south
case north
}
let directionSet: Set = [Direction.north, Direction.east]
struct Dog {
var name: String
var age: Int
}
extension Dog: Hashable {}
// 이렇게 전체 구현할 필요 없음
//extension Dog: Hashable {
// func hash(into hasher: inout Hasher) {
// hasher.combine(name)
// hasher.combine(age)
// }
//}
let dog1: Dog = Dog(name: "초코", age: 10)
let dog2: Dog = Dog(name: "보리", age: 2)
let dogSet: Set = [dog1, dog2]
class Person {
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
// Set에 넣고 싶어서, Hashable 프로토콜 채택 ====> 클래스에서는 에러 발생 ===> hash(into:)메서드 직접구현해야함
// extension Person: Hashable {}
extension Person: Hashable {
func hash(into hasher: inout Hasher) {
hasher.combine(name)
hasher.combine(age)
}
// == 연산자도 직접구현해야함
static func == (lhs: Person, rhs: Person) -> Bool {
return lhs.name == rhs.name && lhs.age == rhs.age
}
}
let person1: Person = Person(name: "홍길동", age: 20)
let person2: Person = Person(name: "임꺽정", age: 20)
let personSet: Set = [person1, person2]
enum Color: CaseIterable { // Int
case red, green, blue
}
//var color = Color.red
//color = .blue
//color = .green
Color.allCases // [Color.red, Color.green, Color.blue]
print(Color.allCases)
//var color2 = Color(rawValue: 0)
//color2 = Color(rawValue: Int.random(in: 0...Color.allCases.count))
// 손쉽게 반복문 사용 가능
for color in Color.allCases {
print("\(color)")
}
// 필요로 하는 곳에서 선언도 간단하게
struct SomeView {
let colors: [Color] = [Color.red, Color.green, Color.blue]
//let colors = Color.allCases
}
// 공식문서의 예제
enum CompassDirection: CaseIterable {
case north, south, east, west
}
// 1) 케이스의 갯수를 세기 편해짐 (케이스를 늘려도 코드 고칠 필요 없음)
print("방향은 \(CompassDirection.allCases.count)가지")
// 2) 배열 ===> 고차함수 이용 가능
let caseList = CompassDirection.allCases
.map({ "\($0)" })
.joined(separator: ", ") // 배열 ===> 문자열화
// "north, south, east, west"
// 랜덤 케이스를 뽑아낼 수 있음
let randomValue = CompassDirection.allCases.randomElement()
enum RpsGame: Int, CaseIterable {
case rock = 0
case paper = 1
case scissors = 2
}
let number = Int.random(in: 0...100) % 3 // 3을 조금 더 멋지게 처리할 수 있는 것은 고급내용에서 다룸
let number2 = Int.random(in: 0...100) % RpsGame.allCases.count // 나머지를 구하는 것이니 무조건 0, 1, 2 중에 한가지임
print(RpsGame.init(rawValue: number)!)