익스텐션
스위프트의 강력한 기능으로, 구조체, 클래스, 열거형, 프로토콜 타입에 새로운 기능을 추가할 수 있게 해준다. 기능을 추가하려는 타입의 구현된 소스 코드를 알지 못하더라도 타입만 알고 있다면 기능을 확장할 수 있다.
익스텐션으로 타입에 추가할 수 있는 것들에는
- 연산 타입 프로퍼티 / 연산 인스턴스 프로퍼티
- 타입 메서드 / 인스턴스 메서드
- 초기화
- 서브스크립트
- 중첩 타입
- 특정 프로토콜을 준수할 수 있도록 기능 추가
새로운 기능을 추가할 수는 있지만 기존에 존재하는 기능을 재정의(override)는 불가능하다. 이것이 바로 상속과의 차이이다.
상속 VS 익스텐션
상속 - 클래스 타입에 활용 - 수직적으로 확장 - 재정의 가능
익스텐션 - 클래스, 구조체, 열거형, 프로토콜 등 모든 타입에 활용 - 수평적으로 확장 - 재정의 불가능
앞서 말했던 것처럼 구현된 소스 코드를 알지 못하더라도 타입만 알고 있다면 기능을 확장할 수 있어 익스텐션은 매우 유용한 기능이다.
구조는 아래와 같고 사용법을 간단하게 작성해보았다.
extension 타입 이름 {
// 타입에 추가될 새로운 기능
}
extension 타입 이름: 준수할 프로토콜 {
// 프로토콜 요구 사항 구현
}
1. 연산 프로퍼티
extension Double { // Double 타입에 두 개의 연산 프로퍼티를 추가
var squared: Double {
return self * self
}
var cubed: Double {
return self * self * self
}
}
let myValue: Double = 3.0
print(myValue.squared)
// 리터럴에 그대로 호출하는 것도 가능
print(3.0.squared)
2. 메소드
extension Double {
func multiply(n: Double) -> Double {
return self * n
}
}
let myValue: Double = 3.0
print(myValue.multiply(5.0))
3. 초기화
extension String {
init(int: Int) {
self = "\\(int)"
}
init(double: Double) {
self = "\\(double)"
}
}
let stringFromInt: String = String(int: 100)
지정 초기화 (Designed Initializer)
- 클래스의 기본 이니셜라이저
- 모든 프로퍼티를 초기화하고 적절한 수퍼 클래스의 이니셜라이저를 호출
- 클래스는 반드시 하나 이상의 지정 초기화를 가지고 있어야 함
class Person {
var name: String
var age: Int
init() {
self.name = ""
self.age = 0
}
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
편의 초기화 (Convenience Initializer)
- 다른 이니셜라이저를 지원하는 보조 이니셜라이저
- 지정 초기화의 일부 매개 변수를 기본 값으로 설정하여 호출
- 지정 초기화와 다르게 반드시 가질 필요는 없음
class Person {
// ... 생략
convenience init(name: String) {
self.init(name: name, age: 25)
}
}
또한 스위프트에서는 지정 초기화와 편의 초기화의 관계를 명확하게 하기 위해 클래스 유형에 대한 초기화 위임 규칙을 정의했다.
- 규칙 1 - 지정 초기화는 부모 클래스에서의 지정 초기화를 호출해야 한다.
- 규칙 2 - 편의 초기화는 동일한 클래스의 다른 초기화를 호출해야 한다.
- 규칙 3 - 편의 초기화는 궁극적으로 지정 초기화를 호출해야 한다.
한 줄로 정리해보면 지정 초기화는 항상 부모 클래스에 위임해야 하고, 편의 초기화는 항상 지정 초기화에 위임해야 한다는 의미이다.
위의 도식도를 보면 자식 클래스의 지정 초기화는 부모 클래스의 지정 초기화에 위임하고 있고, 편의 초기화는 동일한 클래스의 지정 초기화에 위임하고 있는 것을 볼 수 있다.
또한 클래스를 정의할 때 옵셔널이 아닌 프로퍼티가 기본 값이 있는 경우 자동으로 기본 초기화(생성자)를 제공한다.
class Person {
var name: String?
var age: Int = 25
}
let p1 = Person() // 컴파일 OK!
let p2 = Person(name: "kodo", age: 25) // 컴파일 Error! -> 해당 매개변수를 갖는 초기화(생성자)가 없기 때문
하지만 옵셔널이 아니면서 기본 값이 없는 경우 컴파일 오류가 발생한다.
class Person {
var name: String
var age: Int = 25
}
let p1 = Person() // 컴파일 Error!
그렇지만 구조체는 다르다. 기본 값이 없는 경우에도 매개변수로 프로퍼티에 대한 값을 넘겨주면 인스턴스가 정상적으로 생성된다.
struct Person {
var name: String
var age: Int
}
let p1 = Person() // 컴파일 OK!
🔗 참고한 것
Initialization — The Swift Programming Language (Swift 5.7)
Initialization Initialization is the process of preparing an instance of a class, structure, or enumeration for use. This process involves setting an initial value for each stored property on that instance and performing any other setup or initialization t
docs.swift.org
익스텐션 - yagom's blog
yagom's blog 익스텐션
blog.yagom.net
'💻 개발 > iOS' 카테고리의 다른 글
[iOS / Swift] lim 클로저 -> 0 (클로저, 극한으로 줄여보기) (0) | 2022.10.05 |
---|---|
[iOS / Swift] 클로저와 프로퍼티, 가볍게 알아보기 (0) | 2022.10.02 |
[TIL] 22.08.25 (0) | 2022.08.25 |
[TIL] 22.08.24 (0) | 2022.08.24 |
[TIL] 22.06.03 (0) | 2022.06.03 |