본 내용은 스위프트 프로그래밍 3판 (야곰 지음) 교재를 공부한 내용을 바탕으로 작성 하였습니다.
익스텐션(extension)
은 구조체, 클래스, 열거형, 프로토콜 타입에 새로운 기능을 추가 해주는 문법이다.
스위프트 타입에 익스텐션을 추가 할 수 있는 기능은 다음과 같다.
또한 상속과 익스텐션의 차이는 상속은 기능을 물려 받아 재정의 하거나 새로운 기능을 추가 할수 있지만, 익스텐션은 기능 추가의 역할만 담당하고 새롭게 재정의 하지는 못한다는 것이다.
그렇다면 원본 클래스나 구조체, 프로토콜에 기능을 추가하면 되지 왜 우리는 extension
을 사용 해야될까?
우리가 만약 외부에서 라이브러리나 프레임워크를 가져다 사용한다면 원본 소스를 수정할 수 없다. 따라서 외부 라이브러리나 프레임워크를 가져와서 extension
으로 기능을 확장해서 쓸수 있으며, 또한 extension
은 protocol
과 연계하여 아주 강력한 기능을 할 수 있다.
extension과 protocol의 관계에 대해서는 다음에 따로 포스트로 정리하려고 한다.
익스텐션의 구현은 extension
키워드를 사용하여 구현하며, 형태는 다음과 같다.
extension 확장할 타입 이름 {
기능 구현
}
다음은 익스텐션으로 연산 프로퍼티 기능을 추가하는 코드이다.
extension Int {
var multipleOfTwo: Bool { //2의 배수인지 확인하는 연산 프로퍼티
return self % 2 == 0
}
var multipleOfFive: Bool { //5의 배수인지 확인하는 연산 프로퍼티
return self % 5 == 0
}
}
var number: Int = 6
print(number.multipleOfTwo) //true
print(number.multipleOfFive) //false
number = 10
print(number.multipleOfTwo) //true
print(number.multipleOfFive) //true
Int
타입에 2의 배수와 5의 배수를 확인하여 Bool 타입을 반환하는 multipleOfTwo
와 multipleOfFive
연산 프로퍼티를 추가하였다.
extension
을 통해 위의 예시와 같이 연산 프로퍼티
를 추가할 수는 있지만 저장 프로퍼티
는 추가할 수 없으며, 프로퍼티 감시자
또한 추가할 수 없다.
다음은 익스텐션으로 메서드를 추가한 코드이다.
extension Int {
var multipleOfTwo: Bool { //2의 배수인지 확인하는 연산 프로퍼티 추가
return self % 2 == 0
}
var multipleOfFive: Bool { //5의 배수인지 확인하는 연산 프로퍼티 추가
return self % 5 == 0
}
func squared() -> Int { //제곱을 만들어주는 메서드 추가
return self * self
}
//Int Type인지 확인하는 타입 메서드 추가
static func isIntTypeInstance(_ instance: Any) -> Bool {
return instance is Int
}
}
var number: Int = 6
print(number.multipleOfTwo) //true
print(number.multipleOfFive) //false
print(number.squared()) //36
print(Int.isIntTypeInstance(number)) //true
number = 10
print(number.multipleOfTwo) //true
print(number.multipleOfFive) //true
print(Int.isIntTypeInstance(number)) //true
제곱을 만들어주는 squared()
인스턴스 메서드와 인스턴스가 Int 타입인지 확인하는 isIntTypeInstance
타입 메서드를 추가 하였다.
이니셜라이저를 추가하여 인스턴스를 초기화할때 데이터를 받아 오도록 추가할 수 있다.
여기서 클래스에 익스텐션으로 이니셜라이저를 추가할때 주의 할 점은 편의 이니셜라이저
는 추가 할 수 있지만 지정 이니셜라이저
는 추가 할 수 없다는 점이다.
지정 이니셜라이저
는 반드시 클래스 구현부에서 구현해야한다.
extension String { //이니셜라이저 추가
init(name: String) {
self = name + "님"
}
}
let personLeeName: String = String(name: "이철수")
print(personLeeName) //이철수님
class Person {
var name: String
init(name: String) {
self.name = name
}
}
extension Person {
convenience init() { // 편의 이니셜라이저 추가
self.init(name: "Unkown")
}
}
let somePerson: Person = Person()
print(somePerson.name) //Unkown
익스텐션으로 서브스립트를 추가할 수 있다.
extension String {
subscript(repeatCount: Int) -> String {
var str: String = ""
for _ in 0..<repeatCount {
str += self
}
return str
}
}
print("hello"[3])
서브스크립트로 Int 타입 매개변수를 받아서 그 숫자만큼 문자열을 반복출력하는 코드를 구현하였다.