Dev/Swift

Swift: 연산자(operator)

두넌 2023. 5. 14.

DAY 06

연산자(Operator)

 

기본 할당 연산자


var x: Int?     // Optional Int
var y: 10       // Int
x = 10          // Optional(10)
x = x! + y      // Optional(20)
x = y           // Optional(10)
  • 할당 연산자(=)는 두 개의 피연산자를 가지고, 왼쪽에 있는 피연산자는 값이 할당되는 변수 또는 상수, 오른쪽에 있는 피연산자는 할당할 값
  • DAY 5에서 배웠던 Optional 변수 x는 값을 unwrapping해서 초기화시켜도 wrapping 되어 저장됨

 

증가 연산자, 감소 연산자


swift 3부터 x++, x--같은 증감 연산자를 지원하지 않음

x+=1, x-=1을 사용해야 함

 

비교 연산자


다른 것들은 다 똑같지만

  • == 연산자는 instance value가 같은지 검사, "equal to"
  • === 연산자는 reference point가 같은지 검사, "idetical to"

 

범위 연산자


닫힌 범위 연산자(closed range operator)

  • x...y
    • x에서 시작하여 y로 끝나는 범위에 포함된 숫자
  • 5...8
    • 5, 6, 7, 8

반 열린 범위 연산자(half-open range operator)

  • x..<y
    • x부터 시작하여 y가 포함되지 않는 모든 숫자
  • 5..<8
    • 5, 6, 7

One-side Ranges

let names = ["A", "B", "C", "D"]
for name in names[2...] {   // 2부터 시작하여 names의 끝까지 포함
    print(name)
}

output

C
D

 

Nil-Coalescing Operator (Nil합병연산자) ??


옵셔널 변수 ?? nil일 때 할당되는 값

옵셔널 변수의 값이 nil 이면 ?? 다음 값으로 할당됨

let defaultColor = "black"
var userDefinedColor: String?   // defaults to nil

var myColor = userDefinedColor ?? defaultColor
// nil이므로 defaultColor - "black" 할당

print(myColor)  // black
userDefinedColor = "red"
myColor = userDefinedColor ?? defaultColor
// nil이 아니므로 원래 값인 "red" 할당

print(myColor)  // red

추가

userDefinedColorOptional<String>이기 때문에, 9번 line에서 myColorOptional<String>로 초기화될 것이라고 생각했지만, Debug 결과 type(of:myColor)에서 String이 출력되었다

이는 아마 연산 과정에서 optional binding을 거치는 것으로 생각된다

 

형 변환(type casting) : as!, as?


다운 캐스팅은 부모 인스턴스를 자식 클래스로 변환하는 데 사용됨

성공 확신이 있으면 as! 키워드를 사용하여 강제 변환(forced conversion)

 

as! 키워드를 사용하여 변환이 되지 않는 경우 crash 발생

성공 확신이 없으면 as? 키워드를 사용하여 안전하게 변환(Optional)

 

as? 키워드를 사용하여 변환이 되지 않는 경우 nil을 리턴하므로, 옵셔널 타입으로 반환

상속 관계가 있는 클래스들끼리만 타입 캐스팅이 가능하며, 자식 인스턴스를 부모로 캐스팅은 문제가 없음

 

업 캐스팅은 객체를 부모 클래스의 객체로 형 변환


형 변환은 성공할 것이기 때문에 보장된 변환(guaranteed conversion)

let myButton: UIButton = UIButton()
let myControl = myButton as UIControl

자식 인스턴스인 myButton을 부모 클래스형으로 형 변환

다음은 부모 클래스의 객체 myScrollView를 자식 클래스 UITextView로 다운 캐스팅

let myScrollView: UIScrollView = UIScrollView()

// (1)
let myTextView = myScrollView as! UITextView
// 부모 인스턴스 as! 자식 클래스

// (2)
if let myTextView = myScrollView as? UITextView {
    print("Type cast to UITextView succeeded")
} else {
    print("Type cast to UITextView failed")
}

(2) 에서 as? 키워드로 type casting을 하였기 때문에, Optional 타입으로 반환된다

그렇기 때문에, Optional binding을 통하여 myTextView 에 unwarpping된 값을 초기화 시켜줄 수 있다

 

as! vs as?


var x: Any = "Hi"
print(x, type(of:x))

x = 10
var y: Int = x as! Int
var z: Int? = x as? Int

print(x, type(of:x))
print(y, type(of:y))
print(z, type(of:z))

output

Hi String
10 Int
10 Int
Optional(10) Optional<Int>

(1) x의 type은 Any이므로 처음 초기화한 값인 "Hi" 에서 String으로 결정된다

(2) x가 10으로 초기화되어 Int형으로 결정된다

(3) y는 x가 forced conversion 되어 형 변환이 이루어진다

(4) z는 x가 Optional conversion 되어 Optional<Int> 타입으로 반환되어 변환된다

 

타입 캐스팅 연산자 정리


as

  • 컴파일 단계에서 캐스팅이 실행되며, 그러므로 언제나 특정 type으로 캐스팅이 성공할 때만 사용이 가능
  • 업 캐스팅 혹은 브릿징에 사용된다
  • (Bridging : Foundation type을 스위프트 표준 라이브러리로 캐스팅)

as?

  • 런 타임에 캐스팅하여 특정 type의 옵셔널을 반환함
  • 성공하면 옵셔널 값을 반환, 실패하면 nil 반환
  • 따라서 반환값은 반드시 옵셔널 타입으로 선언하여 받아야 함

as!

  • 런 타임에 특정 type으로 강제 캐스팅
  • 캐스팅 실패할 경우 런타임 에러 발생할 수 있음

 

다운 캐스팅은 실패할 수도 있기 때문에, 두 가지 연산자가 있음

as? 연산자를 이용하여 다운캐스팅 하고 반환된 옵셔널 값을 if-let 구문으로 처리하는 방법이 가장 일반적인 방법

캐스팅은 실제로 인스턴스를 수정하거나 그 값을 변경하지 않으며 단순히 캐스팅 된 타입으로 해당 인스턴스를 처리 및 접근

 

타입 검사(is - type check)


객체가 해당 Class의 인스턴스인지 검사

if myobject is MyClass {
    // myobject는 MyClass의 인스턴스이다
}

 

Reference


Operator Declarations - Apple Developer

댓글