연산자(Operator)
연산자의 우선순위와 결합 법칙
Operator Declarations | Apple Developer Documentation
Operator Declarations | Apple Developer Documentation
Work with prefix, postfix, and infix operators.
developer.apple.com
스위프트의 연산자에 대해 살펴볼 수 있는 사이트이다.
Swift Operator precedence and associativity (With Examples) (programiz.com)
Swift Operator precedence and associativity (With Examples)
Operator precedence is a set of rules that determines which operator is executed first. Before you learn about operator precedence, make sure to know about Swift operators. Let's take an example, suppose there is more than one operator in an expression. va
www.programiz.com
연산자의 우선 순위와 결합성에 대해 살펴볼 수 있는 사이트이다.
Basic Operators | Documentation (swift.org)
Documentation
docs.swift.org
마찬가지로 연산자에 대해 살펴볼 수 있다.
기본 할당 연산자
= (할당 연산자)는 두 개의 피연산자를 가지며 오른쪽 피연산자의 값을 왼쪽 피연산자로 대입한다.
산술 연산자
일반적으로 두 개의 피연산자를 가지는 연산자이다. 예외로는 단항 마이너스 연산자인 -가 있다. (음수를 나타냄)
+ - (단항 -> 음수표시) - (뺄셈) * / %
ex)
i - 2
i / 5
i % 7
복합 할당 연산자
변수가 여러 개 있을 때 변수끼리 더하거나 빼거나... 한 값을 다시 어떤 변수에 대입한다.
| x += y | x와 y를 더한 값을 x에 대입 |
| x -= y | x에서 y를 뺀 값을 x에 대입 |
| x *= y | x와 y를 곱한 값을 x에 대입 |
| x /= y | x를 y로 나눈 값을 x에 대입 |
| x %= y | x를 y로 나눈 나머지를 x에 대입 |
| x &= y | x와 y의 bit AND 연산을 한 뒤 x에 대입 |
| x |= y | x와 y의 bit OR 연산을 한 뒤 x에 대입 |
ex)
x = x + y
x *= y
증가 연산자와 감소 연산자
x의 값을 증가, 감소 시키는 방법은 여러 가지가 있다.
x = x + 1
x += 1
하지만 다른 많은 언어에서 지원하는 ++와 --은 스위프트에서 사용할 수 없다. Swift 3 이전에는 존재했지만 지금은 사용할 수 없다.
let x = 3
// x-- -> 사용할 수 없음!
// 대신 아래의 것들을 사용할 것!
x = x - 1
x -= 1
비교 연산자
두 값을 비교해서 Boolean 값을 반환한다.
| x == y | x와 y가 같으면 true |
| x != y | x와 y가 다르면 true |
| x > y | x가 y보다 크면 true |
| x >= y | x가 y보다 크거나 같으면 true |
| x < y | x가 y보다 작으면 true |
| x <= y | x가 y보다 작거나 같으면 true |
논리 연산자
NOT(!), AND(&&), OR(||), XOR(^)가 있다.
| ! | 현재 상태를 뒤집음(true -> false, false -> true) |
| && | 비교하는 두 피연산자가 모두 참이면 true |
| || | 비교하는 두 피연산자 중 하나라도 참이면 true |
| ^ | 비교하는 두 피연산자의 상태가 서로 다르면 true |
범위 연산자
닫힌 범위 연산자 (Closed Range Operator)
x...y
x로 시작, y로 끝나는 범위의 숫자를 의미한다.
for i in 3...7 {
print(i)
}
/* 실행 결과
3
4
5
6
7
*/
반 열린 범위 연산자 (Half-Open Range Operator)
x..<y
x로 시작, y보다 작은 범위의 숫자를 의미함 x...y에서 y를 제외한 것과 같다.
for i in -3..<3 {
print(i)
}
/* 실행 결과
-3
-2
-1
0
1
2
*/
단방향 범위 연산자 (One-Sided Ranges)
...x
x...
..<x
x보다 작거나 큰 값들 또는 x보다 작은 값 중 x를 제외한 값을 나타낸다. 최소, 최대 방향으로 계속 이동하다 보니 배열의 인덱스와 같은 한정된 범위의 내에서 사용 가능하다.
let arr = ["a", "b", "c"]
for i in arr[...2] { // 0, 1, 2
print(i)
}
print()
for i in arr[2...] { // 2
print(i)
}
print()
for i in arr[..<2] { // 0, 1
print(i)
}
/* 실행 결과
a
b
c
c
a
b
*/
삼항 연산자
[조건] ? [참 표현식] : [거짓 표현식]
다른 언어에서 지원하는 그것과 똑같다.
Nil 합병 연산자
x ?? y
옵셔널 변수 x의 값이 nil이면 y를 반환한다.
var aa : String?
let bb = "안녕 넌 nil이야"
aa = "nil아님"
var result = aa ?? bb // aa가 nil이면 bb가 저장됨
print(result)
/* 실행 결과
nil아님
*/
var aa : String?
let bb = "안녕 넌 nil이야"
var result = aa ?? bb // aa가 nil이면 bb가 저장됨
print(result)
aa = "나 이제 nil 아니야" // aa는 이제 nil이 아니다
result = aa ?? bb // aa가 nil이면 bb가 저장됨
print(result)
/* 실행 결과
안녕 넌 nil이야
나 이제 nil 아니야
*/
클래스 vs 객체 vs 인스턴스
클래스는 객체의 타입으로, 객체를 정의해 놓은 것을 의미한다.
객체와 인스턴스는 비슷한 의미이지만 정확히는 클래스로부터 만들어낸 객체를 인스턴스라고 한다.
https://en.wikipedia.org/wiki/Class_(computer_programming)
Class (computer programming) - Wikipedia
From Wikipedia, the free encyclopedia Definition in programming that specifies how an object works In object-oriented programming, a class is an extensible program-code-template for creating objects, providing initial values for state (member variables) an
en.wikipedia.org
형변환
스위프트는 Type Safety 언어이다.


let x = 10
let y = 2.0
//print(x / y) // 오류 발생!
print(Double(x) / y)
/* 실행 결과
5.0
*/
업캐스팅 시는 as를 다운캐스팅 시에는 as! 나 as?를 사용한다. 일반적으로 업캐스팅은 자식 클래스가 부모 클래스가 가진 것을 가지고 있기 때문에 안전하게 사용할 수 있지만 다운캐스팅의 경우는 부모 클래스를 자식 클래스의 타입으로 변환시키는 것이기 때문에 확실하게 안전하다고는 말할 수 없다. 그렇기 때문에 as에 !를 붙인 as! 를 사용할 때는 무조건 안전하게 사용할 수 있다는 확신을 가지고 있을 때만 사용해야 한다. as? 의 경우는 변환이 안 될 경우 nil을 반환한다.
타입 검사 is
is로 어떤 타입인지 검사할 수 있다.
let x = "난 String"
let y = 123
if x is String { // String이면 실행 -> 참
print(x)
}
else {
print(123)
}
if x is Int { // Int이면 실행 -> 거짓
print(x)
}
else {
print(123)
}
/* 실행 결과
난 String
123
*/
class A{}
class B{}
let a = A()
if a is B { // a의 타입은 B와 같을까?
print("a의 타입은 B야");
}
else {
print("a의 타입은 B가 아니다..!")
}
/* 실행 결과
a의 타입은 B가 아니다..!
*/
Optional


var aa : String? = "nil 아님"
var bb : String? // 초기화 하지 않았다.
print(aa!, bb!) // 값을 설정하지 않은 bb의 값을 가져오려고 함
/* 실행 결과
main/main.swift:4: Fatal error: Unexpectedly found nil while unwrapping an Optional value
... 오류 발생
*/
Optional을 ?나 !로 선언 하는 것은 똑같다. 약간 다른 점이 있긴 한데 그 점은 이후에 알아보자. Optional 변수를 선언하고 초기값을 지정해주지 않으면 nil로 초기화되므로 조심해야 한다.
print(Double(1.5))
print(Double(1))
print(Double("1.5")) // 어떻게든 변환 가능
print(Double("abc")) // 변환 불가
/* 실행 결과
1.5
1.0
Optional(1.5)
nil
만약 어떤 값을 사용하고자 할 때 오류가 발생할 가능성이 있다면 그 결과는 Optional로 반환된다. 어떻게든 변환할 수 있으면 그 값이 Optional로 저장되지만 그렇지 않다면 nil로 저장된다.
print(Double(1.5))
print(Double(1))
print(Double("1.5")!)
//print(Double("abc")!) // 오류 발생함 nil을 풀려고 했기 때문
/* 실행 결과
1.5
1.0
1.5
*/
물론 위와 같이 Optional을 바로 풀어버리는 것도 가능하다.
강제 언래핑(Forced Unwrapping)
var x : Double? = 1.5
var y : Double = 3.7
print(x)
print(x!)
//print(x + y) // optional(1.5) + 3.7이므로 에러 발생
print(x! + y) // 1.5 + 3.7이므로 에러 발생하지 않음
x = x! + y
print(x) // 값을 다시 대입해도 optional로 저장된다.
/* 실행 결과
Optional(1.5)
1.5
5.2
Optional(5.2)
*/
Optional에 들어 있는 값을 가져오는 방법은 여러 가지가 있다. 그중 첫 번째로 알아볼 것이 위의 방법이다. !로 강제 언래핑하는 방법이다. 이렇게 하면 값을 가져오기는 편하지만 위에서 살펴봤듯이 그 값이 nil이라면 에러가 발생하게 된다. 그리고 Optional 변수에 다시 어떤 언래핑한 값을 대입하더라도 그대로 Optional인 점을 알아두자.
var str : String?
if str != nil {
print("str은 nil이 아니다")
}
else {
print("str은 nil이야")
}
/* 실행 결과
str은 nil이야
*/
에러를 방지하기 위해 위와 같은 조건문을 이용할 수도 있다.
var str : String?
if str!=nil {
print(str + "은 nil이 아니다")
}
else {
print("str은 nil이야")
}
/* 실행 결과
main.swift:3:8: error: use of '=' in a boolean context, did you mean '=='?
if str!=nil {
~^~~~
==
main.swift:3:9: error: 'nil' cannot be assigned to type 'String'
if str!=nil {
^
main.swift:4:11: error: value of optional type 'String?' must be unwrapped to a value of type 'String'
print(str + "은 nil이 아니다")
*/
띄어쓰기를 항상 조심하자.
Optional의 값을 가져오는 연산자인 !는 우선순위가 높기 때문에 x! = 10를 !=와 같은 연산자처럼 붙여 쓰게 되면 원래와는 다른 결과가 나오게 된다. 근데 그 이전에 값에 값을 대입하는 것이 말이 안 되긴 하다.
옵셔널 바인딩(Optional Binding)
var str : String? = "안녕"
if let hello = str { // 옵셔널 바인딩
print(hello)
}
else {
print("str은 nil이야")
}
/* 실행 결과
안녕
*/
이전과 같이 조건문에서 nil 검사를 하지 않아도 Optional의 값을 가져와 사용할 수 있는 방법이 있다. 그것이 옵셔널 바인딩이라고 하는 방법이다. if문 조건 부분에서 변수를 선언한 뒤 바로 Optional 변수를 대입해 주면 된다. 그러면 그 이후로는 새롭게 선언한 변수를 이용하여 Optional의 값을 사용할 수 있다.
var str : String? // 초기화 값을 지정해주지 않음
if let hello = str { // 무시된다.
print(hello)
}
else {
print("str은 nil이야")
}
/* 실행 결과
str은 nil이야
*/
만약 값이 없다면 if문을 실행하지 않고 else문으로 이동한다.
var str : String? = "나도 str이야"
if let str = str { // 변수명을 똑같이 지정했다.
print(str)
}
else {
print("str은 nil이야")
}
/* 실행 결과
나도 str이야
*/
만약 변수명을 똑같이 지정한다고 해도 상관없다. str이 if문 블록 안에서는 Optional("나도 str이야")가 아닌 "나도 str이야" 로 사용된다.
var str : String? = "나도 str이야"
if let str { // Optional 변수와 같은 이름으로 지정함
print(str)
}
else {
print("str은 nil이야")
}
/* 실행 결과
나도 str이야
*/
극한의 효율을 위한 더 짧은 사용 방법이 존재한다. let str = str이 아닌 그냥 let str처럼 Optional 변수와 같은 변수명만 써도 동일하게 작동한다. 이 방법은 Optional Binding의 Short Form으로 스위프트 5.7 버전부터 지원한다.
var apple : String? = "나는 사과야"
var banana : String? = "나는 바나나야"
if let a = apple, let b = banana { // Optional 변수 여러 개를 한번에 사용
print(a, b)
}
else {
print("nil이야")
}
/* 실행 결과
나는 사과야 나는 바나나야
*/
if문 안에서 Optional 변수 여러 개를 한 번에 사용할 수 있다.
var apple : String? = "나는 사과야"
var banana : String? // 초기화 값을 지정해 주지 않음
if let a = apple, let b = banana { // 실행 안 됨
print(a, b)
}
else {
print("누군가가 nil이야...")
}
/* 실행 결과
누군가가 nil이야...
*
,는 and의 역할을 하기 때문에 b가 nil이어서 if문 블록을 실행하지 않고 else 블록을 실행한다.
var apple : String? = "나는 사과야"
var banana : String? = "나는 바나나야"
if let apple, let banana {
print(apple, banana)
}
else {
print("nil이야")
}
/* 실행 결과
나는 사과야 나는 바나나야
*/
여러 개로 작성해도 역시 Short Form을 사용할 수 있다.
암묵적 언래핑 (Implicitly Unwrapped Optional)
앞에서 일단 넘어갔었던 Optional 변수 지정 시에 !를 사용하는 방법이다. !를 사용하여 Optional 변수를 지정하면 필요할 때(Optional로 사용되지 않을 때) 자동으로 값을 풀어서 넘겨준다.
하지만 Optional과 그것을 푼 값이 모두 가능한 곳에서는 Optional으로 지정된다.
var aa : Double! = 1.7
var bb : Double = aa // Double 값이 필요하므로 1.7이 저장됨
print(aa) // Optional(1.7)과 1.7 모두 가능하므로 Optional(1.7)이 들어감
print(bb) // 이전에 1.7을 저장했으므로 1.7이 출력됨
/* 실행 결과
Optional(1.7)
1.7
*/
위와 같이 Optional과 언래핑한 값이 모두 가능하다면 Optional로 사용되는 것을 알 수 있다.
var aa : Double! = 1.7
var bb : Double = aa // Double 값이 필요하므로 1.7이 저장됨
print(aa) // Optional(1.7)과 1.7 모두 가능하므로 Optional(1.7)이 들어감
print(bb) // 이전에 1.7을 저장했으므로 1.7이 출력됨
print(aa + bb)
var cc : Double? = 3.5
print(cc! + aa) // 3.5 + 1.7
print(type(of: aa), type(of: bb), type(of: cc))
/* 실행 결과
Optional(1.7)
1.7
3.4
5.2
Optional<Double> Double Optional<Double>
*/'공부 > Swift' 카테고리의 다른 글
| [Swift][9주차] Xcode 및 Mac 사용 (0) | 2023.10.30 |
|---|---|
| [Swift][6주차] 클로저, 클래스 (0) | 2023.10.16 |
| [Swift][5주차] 함수(메서드), guard, 일급객체 및 클로저 (0) | 2023.10.02 |
| [Swift][4주차] 제어문 및 함수와 메서드 (0) | 2023.09.25 |
| [Swift][1, 2주차] Swift 들어가기 및 자료형 (0) | 2023.09.11 |