# 1.3 오브젝티브-C vs 스위프트

&#x20;오브젝티브-C를 대체할 목적으로 스위프트가 출현했을 때 많은 사람들의 관심은 '과연 스위프트가 오브젝티브-C를 대체할 수 있을까'였죠. 언어를 대체한다는 것은 기존 언어가 담당하던 모든 역할을 처리할 수 있는 역량이 되어야 가능하기 때문입니다. 두 언어 사이의 공통점과 차이점에 대해서 알아봅시다.

### 파일 통합

&#x20;오브젝티브-C는 C를 기초로 하여 만들어진 언어이므로 파일 구조도 C처럼 헤더 파일과 소스 파일로 구분됩니다. 선언과 구현이 분리되는 형태죠. 그러나 스위프트는 헤더 파일과 소스 파일이 모두 .swift 확장자를 갖는 파일 하나로 통합되었습니다. 변수나 상수, 각종 객체의 형식에 대한 선언과 실질적인 내용 구현이 모두 하나의 파일에서 이루어집니다.

### 클래스의 정의와 구현

&#x20;클래스를 작성할 때 오브젝티브-C는 헤더 파일에 클래스의 인터페이스를 정의하고, 스스 파일에는 정의된 인터페이스를 구현합니다. 그러나 스위프트에서는 클래스의 인터페이스 정의 없이 바로 클래스를 구현하면 됩니다.&#x20;

&#x20;또한 오브젝티브 C는 반드시 클래스 선언 시 반드시 상위 클래스를 상속 받아야 하며, 아무것도 상속 받을 필요가 없을 때라도 최상위 클래스인 NSObject를 상속받아야 하지만, 스위프트에서는 상속받아야 할 클래스가 없으며 정말 아무것도 상속받지 않아도 됩니다.

{% code title="오브젝티브-C : 클래스 선언 - 헤더 파일" %}

```objectivec
@interface Player : NSObject
@end
```

{% endcode %}

{% code title="오브젝티브-C :  클래스 구현 - 소스 파일" %}

```objectivec
@implementation Player
@end
```

{% endcode %}

{% code title="스위프트 파일 : 클래스 구현" %}

```swift
class Player {

}
```

{% endcode %}

### 상속

&#x20;오브젝티브-C는 다중 상속을 지원하지 않지만, 프로토콜(Protocol)을 정의하여 클래스 객체가 준수해야 할 형식을 제공할 수 있습니다. 또한 카테고리(Category) 개념을 통해 상속 대신 기존 객체 자체를 직접 확장할 수 있습니다.

&#x20;스위프트도 마찬가지 입니다. 다중 상속을 지원하지 않으며 프로토콜을 정의할 수 있습니다. 또한, 기존 객체를 직접 확장할 수 있도록 Extension이 제공되는데, 이는 오브젝티브-C의 카테고리에 대응하는 개념입니다. 단, 오브젝티브-C에서 클래스 객체만 확장할 수 있었던 카테고리에 비해 스위프트의 Extension은 클래스, 구조체, 프로토콜 등 대부분 객체에 적용할 수 있습니다.

### 범용 타입

&#x20;오브젝티브-C에서는 모든 데이터 타입을 저장할 수 있는 범용 타입 객체가 필요할 때가 있는데, 이와 같은 범용 타입으로 id 타입을 제공합니다. id 타입은 모든 타입의 데이터를 저장할 수 있을 뿐만 아니라, 호환성만 보장된다면 저장된 데이터를 어떠한 타입으로든 변환할 수 있는 특성을 가지고 있습니다.

&#x20;스위프트 역시 동일한 코코아 프레임워크나 코코아 터치 프레임워크를 사용하기 때문에, 오브젝티브-C의 id 타입에 대응하는 범용 타입의 객체가 필요합니다. 이 때문에 제공되는 것이 Any 타입과 AnyObject 클래스 입니다. Any는 구조체, 클래스, 열거형, 함수 등 스위프트에서 제공하는 모든 타입의 값을 저장할 수 있는 타입인 반면, AnyObject는 클래스에 한해 범용으로 사용 가능한 데이터 타입입니다.

### 메소드 호출

&#x20;오브젝티브-C는 스몰토크의 문법을 차용한 결과, 메소드 호출을 메시지 전송 방식으로 처리합니다. 즉, 객체의 메소드를 호출하는 대신 객체에 메시지를 보내서 필요한 기능을 처리합니다. 객체와 메세지는 공백을 통해 연결되며 대괄호를 사용하여 메시지 전송 단위를 감싸서 구분합니다. 그러나 스위프트는 일반적인 객체지향에서의 메소드 호출 방식을 따릅니다. 객체와 메소드 사이는 점( . )을 통해 연결되고, 메소드 호출 단위를 감싸는 구분자는 사용하지 않습니다.

### nil의 의미

&#x20;오브젝티브-C에서는 존재하지 않는 객체에 대한 참조를 위해 nil이라는 상수를 사용합니다. 일반적으로 nil은 클래스 객체를 참조하는 데에 사용되고, NULL은 그 밖에 다른 포인터 자료형에 사용됩니다.

```
// 객체의 빈 참조에 사용되는 nil
UIViewController *uvc = nil

// 포인터 자료형의 빈 참조에 사용되는 NULL
int *sPtr = NULL;
```

&#x20;반면, 스위프트에서 nil은 옵셔널 타입의 기본값으로 사용되며 '값이 존재하지 않음'을 의미합니다. 스위프트에서는 NULL 상수가 정의되어 있지 않습니다.

```swift
// 옵셔널 타입의 기본값으로 nil이 대입
var name : String? = nil
```

### 포인터 사용

&#x20;오브젝티브-C는 C의 포인터 문법을 그대로 물려받았습니다. 객체에 대한 인스턴스 변수를 정의할 때에는 항상 포인터를 사용하는 레퍼런스 참조를 기본으로 사용했죠. 포인터를 사용해야 한다는 것은 초보자들에게는 적지 않은 부담으로 작용했습니다.

&#x20;스위프트에서는 이러한 포인터 개념을 제거하여 개발자가 직접 레퍼런스를 참조하지 않도록 하는 대신, 객체의 종류에 따라 컴파일러가 직접 레퍼런스를 참조할 것인지 아니면 객체를 복사할 것인지를 결정합니다.

### 객체지향 타입

&#x20;오브젝티브-C는 객체지향을 위한 타입으로 클래스를 제공합니다. @Interface 어노테이션을 이용하여 형식을 선언하고, @Implementation 어노테이션을 이용하여 실질적인 내용을 구현하죠. 이렇게 작성된 클래스를 사용할 때에는 인스턴스를 생성하여 사용합니다.

&#x20;그러나 스위프트에서는 객체지향용 타입으로 클래스뿐만 아니라 구조체, 열거형까지 제공합니다. 이들 객체 타입은 모두 인스턴스를 만들 수 있으며 인스턴스와 관련된 변수, 상수를 속성(property)으로 선언하여 사용할 수 있습니다. 그뿐만 아니라 이들 객체 타입에 인스턴스 메소드와 타입 메소드를 작성하여 사용할 수도 있습니다.

```swift
// 클래스(Class)
class SampleClass {
}
// 구조체(Structure)
struct SampleStruct {
}
// 열거형(Enumeration)
enum SampleEnum {
}
```

### 익명 함수

&#x20;현대 프로그래밍 개념에서 익명 함수의 사용은 람다 함수를 사용할 수 있게 해주는 리스트, 스킴 같은 함수형 프로그래밍 언어로부터 도입되었다고 할 수 있습니다. 람다 함수는 함수 기반으로 정의되는 코드 내에서 한 번만 사용하면 되는 코드마저 함수로 선언해서 사용해야 하는 번거로움을 피할 수 있게 해 줌으로써 코드를 더욱 간결하게 만들어 줍니다.

&#x20;람다 함수는 오브젝티브-C에서는 블록(Block)이라는 개념으로 익명 함수를 표현할 수 있었는데, 이 기능이 스위프트에서는 클로저를 이용한 익명 함수 정의 문법으로 제공됩니다.

### 오류 처리

&#x20;일반적으로 객체 지향 언어에서 제공하는 오류 처리 기능은 오류 발생이 예상되는 지점에 미리 오류를 검출하는 코드를 작성해두고, 실제로 오류가 발생할 때 정해진 코드 블록 바깥으로 오류 정보를 던져 처리할 수 있도록 지원하는 방식입니다. 오브젝티브-C에서도 오류를 검출하기 위한 기능은 제공되었지만, 이는 읽고 쓸 수 있는 매개변수를 사용하여 오류를 검출해내는 방법이었을 뿐 오류 처리를 위한 구문이 별도로 제공된 것은 아니였습니다.

&#x20;스위프트에서는 Try \~ Catch 구분을 채택하여 코드를 실행하는 과정에서 오류가 발생하더라도 프로그램이 중단되는 것을 막아주고, 미리 준비된 대응 구문을 실행하여 효율적으로 오류에 대응할 수 있게 합니다.
