연산자
연산자는 다른언어와 비슷한 부분이 많아 몰랐던 부분만 작성하였습니다.
5.1.5 범위 연산자
값(수)의 범위를 나타내고자 할 때 사용합니다.
폐쇄 범위 연산자 : A...B : A부터 B까지의 수를 묶어 범위를 표현합니다.
반폐쇄 범위 연산자 : A.. < B : A부터 B 미만까지의 수를 묶어 범위를 표현합니다. A를 포함하고 B는 포함하지 않습니다.
단방향 범위 연산자 :
A... : A 이상의 수를 묶어 범위를 표현합니다.
...A : A 이하의 수를 묶어 범위를 표현합니다.
.. < A : A 미만의 수를 묶어 범위를 표현합니다.
텍스트로 봐서는 범위연산자가 어떤 값들의 범위를 나타내는것 같은데 어떻게 사용되는지 모르겠다.
뒤에 반복문에서 코드를 통해 더 자세히 살펴보자.
5.1.9 오버플로연산자
프로그래밍에서 정수 타입의 최댓값과 최솟값이 존재하고 이를 넘거나 더 낮게 내려가면 오버플로우가 발생한다.
스위프트에서는 오버플로우가 발생 할 때 에러가 아닌 0 또는 최댓값으로 다시 돌아가는 연산자가 존재한다.
코드를 통해 살펴보자
var unsignedInteger: UInt8 = 0
//let errorUnderflowResult: UInt8 = unsignedInteger - 1
let underflowedValue: UInt8 = unsignedInteger &- 1 // 255
unsignedInteger = UInt8.max
//let errorOverflowResult: UInt8 = unsignedInteger + 1
let overflowedValue: UInt8 = unsignedInteger &+ 1 // 0
5.1.10 기타 연산자
자바스크립트 언어는 없는 옵셔널과 nil에 관한 연산자가 존재한다.
nil 병합 연산자 : A ?? B (A가 nil이 아니면 A를 반환하고, A가 nil이면 B를 반환합니다.)
부호변경 연산자 : -A (A(수)의 부호를 변경합니다.)
옵셔널 강제 추출 연산자 : O! (O(옵셔널 개체)의 값을 강제로 추출합니다.) // 지양하는게 좋다.
옵셔널 연산자 : V? (V(옵셔널 값)을 안전하게 추출하거나, V(데이터 타입)가 옵셔널임을 표현합니다.)
nil 병합 연산자는 옵셔널을 사용할 때 유용한 방법입니다.
위 코드에서도 사용을 했었고, 아래코드처럼 nil일 때, nil이 아닐 때 값을 설정 할 수 있습니다.
let valueInt: Int = someOptionalInt != nil ? someOptionalInt! : 0
// 위 코드와 동일한 결과
let valueInt: Int = someOptionalInt ?? 0
5.3 사용자 정의 연산자
*, +, -, <, / 등등 다양한 연산자를 언어에서 사용 할 수 있습니다.
스위프트에서 개발자가 직접 연산자를 만들어 사용 할 수 있습니다.
사용자 정의 연산자는 아스키 문자 /, =, -, +, !, *, %, <. >, &, |, ^, ?, ~ 를 결합해서 사용합니다.
5.3.1 전위 연산자 정의와 구현
Int 타입의 제곱을 구하는 연산자로 **을 전위연산자로 사용하려고 할때, 아래와 같이 구현합니다.
prefix operator **
// Int형 타입의 제곱을 구현하겠다.
prefix func ** (value: Int) -> Int {
return value * value
}
let minusFive: Int = -5
let sqrtMinusFive: Int = **minusFive
print(sqrtMinusFive)
String 형으로도 구현을 할 수 있습니다.
prefix operator **
perfix func ** (value: String) -> String {
return value + " " + value
}
let reulstString: String = **"kemi"
print(resultString) // kemi kemi
전위, 후위 연산자도 비슷한 방법으로 생성이 가능합니다.
== 연산자도 동작을 바꿔줄 수 있습니다.
class Car {
var modelYear: Int? // 연식
var modelName: String? // 모델 이름
}
struct SmartPhone {
var company: String? // 제조사
var model: String? // 모델
}
// Car 클랫의 인스턴스끼리 == 연산 했을 때 동작하는 함수
func == (lhs: Car, rhs: Car) -> Bool {
return lhs.modelName == rhs.modelName
}
// SmartPhone 구조체의 인스턴스끼리 == 연산했을 때 동작하는 함수
func == (lhs: SmartPhone, rhs: SmartPhone) -> Bool {
return lhs.model == rhs.model
}
let myCar = Car()
myCar.modelName = "S"
let yourCar = Car()
yourCar.modelName = "S"
var myPhone = SmartPhone()
myPhone.model = "SE"
var yourPhone = SmartPhone()
yourPhone.model = "6"
print(myCar == yourCar)
print(myPhone == yourPhone)
지금것 연산자 함수를 전역함수로 구현을 했습니다.
특정 타입에 군한된 연산자함수라면 그 타입 내부에 구현되는 것이 읽고 이해하는게 쉽습니다.
아래 코드와 같이 class 내에서 연산자 함수를 구현 할 수 있습니다.
class Car {
var modelYear: Int? // 연식
var modelName: String? // 모델 이름
// Car 클랫의 인스턴스끼리 == 연산 했을 때 동작하는 함수
static func == (lhs: Car, rhs: Car) -> Bool {
return lhs.modelName == rhs.modelName
}
}
struct SmartPhone {
var company: String? // 제조사
var model: String? // 모델
// SmartPhone 구조체의 인스턴스끼리 == 연산했을 때 동작하는 함수
static func == (lhs: SmartPhone, rhs: SmartPhone) -> Bool {
return lhs.model == rhs.model
}
}
let myCar = Car()
myCar.modelName = "S"
let yourCar = Car()
yourCar.modelName = "S"
var myPhone = SmartPhone()
myPhone.model = "SE"
var yourPhone = SmartPhone()
yourPhone.model = "6"
print(myCar == yourCar)
print(myPhone == yourPhone)
사용자 정의 연산자는 복잡한 연산을 하나의 특수문자로 구현하기 때문에 코드가 깔끔해 질 수 있습니다.
하지만 저는 이런 연산자 사용하는 건 지양할 것 같습니다.
기존 스위프트에서 제공한다고 착각 할 수 도 있고, 사용자 정의 연산자를 선언 한 것을 인지하지 못한다면 유지보수 할 때도 힘들어보이기 때문에 사용하진 않을 것 같습니다.
'Swift > Swift 기본문법' 카테고리의 다른 글
| Swift 기본 문법 - 8. 반복문 (0) | 2022.01.17 |
|---|---|
| Swift 기본 문법 - 7. 흐름제어 (if, switch) (0) | 2022.01.16 |
| 스위프트 기본문법 - 5. 세트(Set) (0) | 2022.01.14 |
| 스위프트 기본문법 - 4. 세트(Set) (0) | 2022.01.13 |
| Swift 기본 문법 - 4. 딕셔너리(dictionary) (0) | 2022.01.13 |
