본문 바로가기

iOS & Swift

Swift 문법 정리 [객체 관련]

Swift 언어를 공부 하면서 암기가 필요한 내용, 특히 기존 배웠던 언어들 과의 차이점에 중점을 둬서 정리함


클래스 기본

  • Swift의 클래스는 대부분 Java와 비슷하게 동작함
  • 용어 변경점
  • 멤버변수 -> 프로퍼티 (var: 가변프로퍼티, let: 불변프로퍼티)
  • static 변수 -> 타입 프로퍼티
  • static 메서드 -> 타입 메서드
  • 주의할 점은 Swift에서는 옵셔널이 아닌 값들에선 nil을 허용하지 않기 때문에 모든 프로퍼티들은 ::각자 초기화::해주거나 ::생성자로 init:: 해주어야함.
    (이 때 만약 옵셔널 프로퍼티가 있다면 초기화는 생략해주어도됨 -> 당연?)
  • Swift에는 소멸할 시 호출되는 디이니셜라이저 deinit도 존재하며, init과 구현방법은 동일.

구조체 / 열거형 기본

1. 구조체 vs 클래스

  • 구조체(+ 열거형)은 Value 타입이고 클래스는 Reference 타입.
  • 클래스는 생성자 init을 따로 구현하여 초기화하지만 구조체는 그냥 값을 넣어서 초기화.
  • Value 타입을 사용하는 경우
  • 연관된 몇몇의 값들을 모아서 하나의 데이터 타입으로 표현하고 싶은 경우
  • 다른 객체 또는 함수 등으로 전달될 때 참조가 아니라 복사(값 복사) 할 경우
  • 자신을 상속할 필요가 없거나, 다른 타입을 상속 받을 필요가 없는 경우
    (구조체에서는 상속이 불가능하다.)
  • Swift에서는 ::모든 기본 데이터 타입이 구조체로 구현::되어있다.

2. Swift에서 String은 Value 타입 이다.

: 위 설명한대로 Swift의 모든 기본 데이터타입은 구조체다. String도 예외는 아니다.
그렇기 때문에 Java와는 달리 String타입도 Value(값) 타입이 된다. 이는 몇가지 차이점을 낳게된다.

  • 객체가 아니기 때문에 단순 ==로 비교한다.
    :바꿔말하면 이제 객체비교가 불가능해진다. Swift에선 자바의 Equals() 메서드와 같은 기능으로 “===“연산자를 사용하는데 이는 값 타입에선 사용할 수 없다.

3. 열거형

기본구조

enum Weekday {
    case mon
    case tue
    case wed
    case thu, fri, sat, sun
}

enum Bool {
    case true
    case false
}
var Day: Weekday = Weekday.mon
  • Switch 구문에서 사용하면 좋다.
  • rawValue(원시값)을 지정할 수 있고 이는 case별로 각각 다른 값을 갖는다.
  • Swift의 열거형에는 메서드를 추가할 수 있다.

클로저

  • 클로저는 실행가능한 코드 블럭이다.
  • 함수는 “이름이 있는 클로저”다 즉 클로저는 함수에서 이름만 떼어낸 것
  • 당연히 1급객체이다.

클로저 문법

기본

{ (매개변수 목록) -> 반환타입 in
    실행 코드
}

{ (a: Int, b: Int) in
    return a + b
}

생략구문

  • 후행 클로저
    : 클로저가 함수의 마지막 전달인자일 때 함수 소괄호 외부에 클로저를 붙여서 구현할 수 있음.
    result = calculate(a: 10, b: 10) { (left: Int, right: Int) -> Int in
      return left + right
    }
  • 반환타입 생략
    : 반환타입이 뚜렷하다면 생략할 수 있음
  • 단축인자 이름
    : 매개변수 이름이 불필요하다면 단축 인자 이름으로 표현하고 매개변수는 생략 가능
  • 암시적 반환 표현
    : 클로저가 반환하는 값이 있다면 마지막줄은 암시적으로 반환값 취급

축악전후 비교

//축약 전
result = calculate(a: 10, b: 10, method: { (left: Int, right: Int) -> Int in
    return left + right
})

//축약 후
result = calculate(a: 10, b: 10) { $0 + $1 }
print(result) // 20

4. 프로퍼티

:Java의 멤버변수와 활용이 거의 동일

1. 연산프로퍼티

  • 구조체, 클래스, 열거형 내부에 구현가능
  • var로만 선언할 수 있으며, get과 set만을 갖는 말그대로 연산용 멤버
  • 읽기전용으로 구성할 수 도 있으며 이땐 get 생략가능
  • set 블럭에선 암시적 매개변수 newValue를 사용할 수 있음
  • 이름 그대로 연산만을 구현하는 프로퍼티이기 때문에 절대로 ::값 자체를 저장할 수 없음::.

2. 프로퍼티 감시자

  • willSet, didSet 으로 이루어져 있고 프로퍼티 감시자를 사용하면 프로퍼티의 값이 변경될 때 원하는 동작을 수행할 수 있음.
  • willSet블럭에선 암시적 매개변수 newValue를 didSet에서는 oldValue를 사용
  • 당연하지만 애초에 값을 저장하지 않는 연산 프로퍼티에서는 사용할 수 없음

5. 프로토콜

  • Java의 인터페이스와 아주 비슷한 역할을 가짐.
  • 프로토콜은 프로퍼티, 메서드, 생성자를 포함할 수 있음
  • 생성자나 메서드의 경우에는 구현부분 없이 매개변수까지만 구현하며, 일반 프로퍼티의 경우 항상 var키워드를 사용하고 중괄호로 {get} or {set} or {get set} 을 명시함

::프로토콜과 인터페이스의 차이는?::

  1. Swift의 프로토콜은 매개변수에 기본 값을 지정할 수 없다.

  2. 프로토콜의 경우 Optional로 멤버를 선언하면 상속시 구현하지 않아도 된다.

    @objc protocol MathProtocol {
    func add(a: Int, b: Int)
    @objc optional func subtract(a: Int, b: Int) 
    }

    이때는 위와같은 구현규칙을 지켜주어야 한다.

  3. static 멤버를 정의할 수 있다.

  4. extension을 통해 객체로 하여금 추가적인 프로퍼티를 상속하게 할 수 있따.

정리
Swift의 프로토콜의 경우 Java의 인터페이스보다 훨씬 많은 기능을 보유하고 있으며, 이는 다른 언어보다 프로토콜이 갖는 위상이 훨씬 높다는 것을 예상할 수 있다.
Swift를 Java처럼 객체지향언어(OOP)가 아니라 프로토콜 지향언어(POP)라고 부르는 이유는 아마 이런 부분에 있을 것이다.