HIT해

Extenstion 본문

Swift/Swift 기초문법

Extenstion

힛해 2024. 8. 7. 04:37
728x90

 

기존 클래스, 구조체, 열거형 타입에 새로운 Property, Method, Initializer 등을 추가하는 것으로

원본 타입(소스 코드) 에 접근하지 못하는 타입들도 확장해서 사용할 수 있다.

extenstion은 코드의 가독성을 높이고, 기능을 모듈화하며, 기존 타입을 더 쉽게 확장할 수 있게 해준다고한다.

 

 

 

extension에 프로퍼티 추가하기

extension Int {
	var zero : Int = 0
}
// 에러 발생

 

저장 프로퍼티는 추가할 수 없으며 , 오로지 연산 프로퍼티만 추가가 가능하기에 오류가 발생한다.

 

그래서 다음과 같이 연산 프로퍼티만 가능하다.

extension Int {
	var half : Int {{
    		return self / 2
         }
}

 

사용할때는 아래와같다.

let num = 40
print(num.half) // 20

 

extension에 메서드 추가하기

extension Int {
    func squared() -> Int {
        return self * self
    }
}

let number = 4
print(number.squared())  // 출력: 16

 

extension Double {
    var km: Double { return self * 1_000.0 }
    var m: Double { return self }
    var cm: Double { return self / 100.0 }
    var mm: Double { return self / 1_000.0 }
}

let distance = 42.0
print(distance.km)  // 출력: 42000.0

 

Struct에서 생성자 추가

구조체에서는 init 함수가 없어도 자동으로 만들 수 있다.

클래스와 달리 모든 프로퍼티를 초기화 할 수 있게 하는 Memberwise라는 생성자를 따로 생성자를 구현하지 않았을 경우 자동으로 제공해서 그렇다.

 

그런데 struct 상에서 내가 생성자를 직접 구현한다면.

 

기존에 제공해주던 Memberwise 를 사용할 수 없게 된다.

이때 extenstion을 사용하면 Memberwise initializer 를 보존하면서 새로운 생성자를 추가할 수 있다.

 

매우 신기하다.

 

기존 함수와 같은 이름을 사용할 수도 있다.

extension String {
    func count(num : Int) -> String {
        print(self) // hit
        var result : String = ""
        for _ in 0..<num {
            result += self
        }
        return result
    }
}


var tmp : String = "hit"

print(tmp.count)

print(tmp.count(num: 5)) // hithithithithithit

 

확장에 중첩 타입 추가하기

extension Int {
    enum Kind {
        case negative, zero, positive
    }
    var kind: Kind {
        switch self {
        case 0:
            return .zero
        case let x where x > 0:
            return .positive
        default:
            return .negative
            }
    }
}

 

이렇게 Int 타입의 extension 안에 Kind 라는 enum을 중첩해서 선언할 수 있고,

 

let num = 100
print(num.kind)      // positive
 
let num2 = -100
print(num2.kind)     // negative

 

사용도 가능하다.

 

코드 가독성이 높아지는 예시를 보자

class ViewController: UIViewController, UITableViewDataSource, UICollectionViewDataSource {
 
    override func viewDidLoad() {
    }
 
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    }
 
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    }
 
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    }
 
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    }
}

위의 코드를 아래와 같이 기능별로 분리할 수 있게 된다.

 

정리한 코드

 

class ViewController: UIViewController {
    override func viewDidLoad() {
    }
}
 
extension ViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    }
 
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    }
}
 
extension ViewController: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    }
 
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    }
}

 

재미있는 기능이고 AF를 공부하다 extension에 대한 의문이 생겨서 공부하게 됐다.