Swift문법 - (16)확장(Extension)

Youth·2022년 10월 2일
0

swift문법공부

목록 보기
16/27
post-thumbnail

확장(Extension)

상속과 확장의 비교

  • (상속 - 수직적 개념) 성격이 비슷한 "타입을 새로"만들어, 데이터를 추가하고, 기능(메서드)을 변형시켜 사용하려는 것
  • (확장 - 수평적 개념) "현재 존재하는 타입"에 기능(메서드)을 추가하여 사용하려는 것
// 기존 타입
class SomeType { }

// 확장
// 기존의 타입에 extension 이라는 키워드를 사용해서 확장
// 새로운 기능을 추가 가능(메서드 형태만 가능)⭐️
// 확장에서 구현한 메서드에 대한 재정의가 불가⭐️(@objc 붙이면 가능)
extension SomeType { }

[사람 → 학생(상속) → 대학생(상속) 구조의 클래스에서]

  • 학생클래스에 extension으로 play()라는 함수를 구현하면 대학생인스턴스에서도 play매서드를 사용할 수 있다.

확장의 장점

  • Int, String, Double모두 구조체로 구현이 되어있기때문에 확장이 가능하다
extension Int {
		// 타입속성이므로 Int.ten으로 10을 사용할 수 있다
    static let ten = 10

		// 계산속성이므로 인스턴스에서 접근하면 된다
		// 10.sqared로 100을 사용할 수 있다
    var squared: Int {
        return self * self
    }
		
		// 메서드이므로 인스턴스에서 접근하면 된다
		// 10.double()로 100을 사용할 수 있다
    func double() -> Int{
        return self * self
    }
}

확장 가능 멤버의 종류

  • (타입) 계산 속성, (인스턴스) 계산 속성, (타입) 메서드, (인스턴스) 메서드
    • 타입저장속성도 구현이 된다 하지만 그냥 저장속성은 구현이 안된다
  • 새로운 생성자 (⭐️ 다만, 클래스의 경우 편의생성자만 추가 가능 / 지정생성자 및 소멸자는 반드시 본체에 구현)
  • 서브스크립트
  • 새로운 중첩 타입 정의 및 사용
  • 프로토콜 채택 및 프로토콜 관련 메서드
  1. 타입 계산 속성의 확장
extension Double {
    static var zero: Double { return 0.0 }
}

Double.zero
  1. 계산 속성의 확장
extension Double {
		// 인스턴스 자신에 1000 곱하기
    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 }
    var ft: Double { return self / 3.28084 }
}

let oneInch = 25.4.mm
// 1인치는 0.0254 미터"
print("1인치는 \(oneInch) 미터")      

let threeFeet = 3.ft
// 3피트는 0.914399970739201 미터"
print("3피트는 \(threeFeet) 미터")     
  1. 타입메서드의 확장
extension Int {
    //구조체의 타입 메서드
    static func printNumbersFrom1to5() {
        for i in 1...5 {
            print(i)
        }
    }
}

Int.printNumbersFrom1to5()
  1. 메서드의 확장
extension String {
    //인스턴스의 매서드
    //"hi"가 세번 출력됨
    func printHelloRepetitions(of times: Int) {
        for _ in 0..<times {
            print("Hello \(self)!")
        }
    }
}

"hi".printHelloRepetitions(of times: 3)

구조체(열거형)에서, 자신의 속성을 변경하는 메서드는 mutating키워드 필요
extension Int {
		// 기존 메서드와 동일하게, mutating 키워드 필요
    mutating func square() {    
        self = self * self
    }
}
var someInt = 3
someInt.square()
someInt // result = 9

멤버의 확장(생성자)

  • 클래스 - 편의 생성자만 구현 가능
  • 구조체(값타입) - 지정생성자 형태로도 (자유롭게) 생성자 구현 가능
  1. 클래스 - 생성자 확장
// UIColor 기본 생성자
var color = UIColor(red: 0.3, green: 0.5, blue: 0.4, alpha: 1)

// 익스텐션 + 편의생성자 조합
extension UIColor {      
    convenience init(color: CGFloat) {
				// 델리게이트어크로스(자기자신의 init을 가져와서 써야한다)
        self.init(red: color/255,
									green: color/255,
								  blue: color/255, alpha: 1)
    }
}
  1. 구조체 - 생성자 확장
struct Point {
    var x = 0.0, y = 0.0
    
		// 내가 생성자를 구현했기 때문에 기본생성자, 멤버와이즈 제공X
    init(x: Double, y: Double) {
        self.x = x
        self.y = y
    }
}

extension Point {
		// 실질적인 편의생성자
    init() {
        self.init(x: 0, y: 0)
    }
}
struct Point {
		// 저장속성이 초기화가 되어있고 아무런 생성자를 생성하지 않은경우
    var x = 0.0, y = 0.0

		// 두가지 생성자가 자동으로 생성이 되어있음
		// init()
		// init(x: Double, y: Double)

}

// 위와같은 경우에 self.init으로 생성자를 호출하지 않고 생성자를 만드는게 가능
extension Point {
		**// 확장에서 생성자를 사용자가 만든다해도**
		**// 기본생성자, 멤버와이즈이니셜라이즈 + 내가만든 생성자 3개 제공**
		init(num: Double) {
				self.x = num
				self.y = num	
		}
}

// 기본값 제공/생성자 구현안함
// 기본 생성자 / 멤버와이즈 생성자가 자동 제공 중
struct Rect {     
    var origin = Point()
    var size = Size()
}

extension Rect {
    // 센터값으로 Rect 생성하는 생성자 만들기
    // 예외적인 경우
		// (저장속성에 기본값 + 본체에 생성자 구현 안한 경우, 여전히 기본생성자/멤버와이즈 생성자 제공)
    init(center: Point, size: Size) {
        let originX = center.x - (size.width / 2)
        let originY = center.y - (size.height / 2)
        
        // (1) 본체의 멤버와이즈 생성자 호출 방식으로 구현 가능
        self.init(origin: Point(x: originX, y: originY), size: size)
        
        // (2) 직접 값을 설정하는 방식으로도 구현 가능
        //self.origin = Point(x: originX, y: originY)
        //self.size = size
    }
}

✅기본생성자와 멤버와이즈 생성자

class Dog {
		// 저장속성이 초기화가 되어있다면 기본생성자를 제공해준다
    var name: String = "보리"
}
Dog()

struct Dog1 {
		// 저장속성이 초기화 되어있다면 기본생성자, 멤버와이즈생성자를 기본제공
    var name: String = "보리"
}
Dog1()
Dog1(name: <#String#>)

struct Dog1 {
    var name: String = "보리"
    var weight: Int = 0
		// 없는것만 따로 찍어낼 수 있는 기본생성자 제공
    var height: Int
}

Dog1(height: <#Int#>)
Dog1(name: <#String#>, weight: <#Int#>, height: <#Int#>)
  1. 멤버의 확장(서브스크립트)
extension Int {
    subscript(num: Int) -> Int {
        
        var decimalBase = 1
        
        for _ in 0..<num {
            decimalBase *= 10
        }
        
        return (self / decimalBase) % 10
        
    }
}

123456789[0] // (123456789 / 1) ==> 123456789 % 10 ==> 나머지 9
123456789[1] // (123456789 / 10) ==> 12345678 % 10 ==> 나머지 8
123456789[2] // (123456789 / 100) ==> 1234567 % 10 ==> 나머지 7
123456789[3] // (123456789 / 1000) ==> 123456 % 10 ==> 나머지 6
  1. 멤버의 확장(중첩타입)
extension Int {
    // 음수인지, 0인지, 양수인지
    enum Kind {       
        case negative, zero, positive
    }
    // 계산 속성으로 구현
    var kind: Kind {    
        switch self {
        case 0:                
            return .zero
        case 1...: 
            return .positive
        default:   
            return .negative
        }
    }
}

func printIntegerKinds(_ numbers: [Int]) {
    for number in numbers {
        switch number.kind {
        case .negative:
            print("- ", terminator: "")
        case .zero:
            print("0 ", terminator: "")
        case .positive:
            print("+ ", terminator: "")
        }
    }
    print("")
}

// + + - 0 - 0 +
printIntegerKinds([3, 19, -27, 0, -6, 0, 7])      
profile
AppleDeveloperAcademy@POSTECH 1기 수료, SOPT 32기 iOS파트 수료

0개의 댓글