포스트

(Deep Dive) Extensions

Extensions는 본질적으로 기존클래스, 구조, 기타데이터유형에 추가 기능을 추가 할 수 있게 한다.

기본형태는 다음과 같다

1
2
3
extension SomeType {
    // new functionality
}

우리가 늘상 만드는 것과 형태가 다르지 않다.

그저 앞에 class, protocol, struct 대신 extension이 사용되었다.

다음과 같은 수가 있고

1
2
3
4
5
6
let myDouble = 3.14159

//반올림
let myRoundedDouble = String(format:"%.1f", myDouble)

print(myRoundedDouble) // 3.1

그런데 문자열을 생성하지않고 만들고 싶다.

1
2
3
var myDouble = 3.14159

print(myDouble.round(to: 3))

하지만 작동하지 않는다.

우리가 직접 작동하게 만들어 보자.

일단 시퀀스는 다음과 같다

1
2
3
4
// ex) 넷째자리에서 반올림한다면?
myDouble=myDouble*1000 // 3141.59
myDouble.round()       // 3142
myDouble=myDouble/1000 // 3.142

extension을 다음과 같이 해주었다.

1
2
3
4
5
6
7
8
9
10
11
extension Double {
    func round(to places: Int) -> Double {
        let precisionNumber = pow(10, Double(places)) // 1000처럼 10의 x제곱 형태로 나타내었다.
        var n = self // 해당수 자신을 10제곱수 곱해야 한다.
        n = n * precisionNumber
        n.round()
        n = n / precisionNumber
        return n
    } 
}

1
print(myDouble.round(to: 3)) // 3.142

이젠 원하는 자리수 만큼 반올림이 가능해졌다.

자세한건 애플 깃허브에 들어가보면 있다

애플이 공개한 오픈 소스들이 있다.

하지만 공개되지 않은 코드들도 많다.

https://github.com/apple/swift

우리가 UIlabel같은 기능을 만들면서 코드에 대해선 접근 권한이 있는건 아니다.

하지만, 클래스들을 확장 할 수 있다.

1
2
3
4
let button = UIButton(frame: CGRect(x:0, y:0, width: 50, height: 50))
button.backgroundColor = .red
button.layer.cornerRadius = 25
button.clipsToBounds = true

이렇게 작성을 하면

그렇다면 UIButton을 확장해서, 버튼의 디자인을 동그랗게 해주게 해보자

1
2
3
4
5
6
extension UIButton {
    func makeCircular() {
        self.clipsToBounds = true
        self.layer.cornerRadius = self.frame.size.width / 2
    }
}

그리고나서 해보면?

1
2
3
4
let button1 = UIButton(frame: CGRect(x:0, y:0, width: 50, height: 50))
button1.backgroundColor = .red

button1.makeCircular()

잘된다!

이렇게 extension은 프로토콜을 확장 할 수 있고,

1
2
3
extension SomeProtocol {
    // Define default behavior
}

저번에 조류를 예로 들었던것을 가져왔다.

1
2
3
4
5
6
7
8
9
10
11
12
13
protocol CanFly {
    func fly()
}

extension CanFly {
    func fly() {
        print("The object takes off into the air")
    }
}

struct Airplane: CanFly {

}

프로토콜에서는 함수의 내용을 정의 할 수 없었다.

즉 우리가 다른 클래스에서 해당 function을 추가하면서 내용을 정의를 했는데,

extension을 사용하면, 프로토콜의 내용을 정의하면서 프로토콜의 function을 default로 사용 할 수가 있다.

airplane에 Canfly 프로토콜을 추가해도 이젠 에러가 발생하지 않는다.

이렇게 입력하는순간 바로 사용가능하게 뜬다!

실제로 작동해보면

The object takes off into the air

결과값도 잘 나오는걸 확인 할 수있다.

그래서 WeatherViewController 에서

class WeatherViewController: UIViewController, UITextFieldDelegate,

이렇게 UITextFieldDelegate 프로토콜을 가져왔음에도 불구하고

함수를 만들지 않아도 에러가 발생하지 않았던 것이다.

extension은 모든 데이터 유형에 대해 다른 프로토콜을 적용 할 수도 있다.

1
2
3
extension SomeType : SomeProtocol {
    // add new functionality
}

해당내용의 예시는 clima(6)과 연관이 되므로 거기서 서술하도록 하겠다

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.