[Swift] 제네릭 (Generics Function)이란?

728x90

제네릭 (Generics Function)이란?

  • 형식에 의존하지 않는 범용 코드 사용
  • 코드의 재사용, 유지보수 용이

코드(예시) & 설명


  • Generic Function
//두형식이 모두 INT여야 한다.
//다른 형식이 필요하다면 개별적으로 만들어야 한다. -> 함수 구현 중복
func swapInteger(lhs: inout Int, rhs: inout Int) {
    let tmp = lhs
    lhs = rhs
    rhs = tmp
}

var a = 10
var b = 20

swapInteger(lhs: &a, rhs: &b)
a
b

//Generic Function 사용하여 해결 -> 코드 작성량 비약적 감소
//T는 새로운 형식이 아니라 문맥에 따라 실제 형식으로 대체되는 place holder일 뿐이다
//코드 개선 : 두 값이 같을때는 굳이 교체 하지 않아도 된다
//Type Constraints : Equatable
func swapValue<T: Equatable>(lhs: inout T, rhs: inout T) {
    if lhs == rhs {
        return

    } // 연산자가 구현되어 있지 않기때문에 비교기능 연산자 직접 구현 해야 된다. -> Type Parameters (형식 제약) 필요

    let temp = lhs
    lhs = rhs
    rhs = temp
}

a = 1
b = 2
swapValue(lhs: &a, rhs: &b)

a
b

var c = 1.2
var d = 3.4

swapValue(lhs: &c, rhs: &d)

c
d

//String 형식을 위한 구현 ( 대소문자 구분없이 비교 )
//Specialization
func swapValue(lhs: inout String, rhs: inout String){
    print("Specialized version")

    if lhs.caseInsensitiveCompare(rhs) == .orderedSame {
        return
    }

    let temp = lhs
    lhs = rhs
    rhs = temp
}

var a1 = 1
var b1 = 2
swapValue(lhs: &a1, rhs: &b1)
a1
b1

var e = "Swift"
var f = "Programming"
swapValue(lhs: &e, rhs: &f)

e
f

  • Generic Types
    • 제네릭 타입을 선언하고 형식 내부에서 사용하는 다양한 형식을 타입 파라미터로 대체하는 방법
/*MARK: 제네릭 타입
class Name<T> {
    code
}
struct Name<T> {
    code
}
enum Name<T> {
    code
}
*/
  • 형식 표기 방식
struct Color<T> {
    var red: T
    var green: T
    var blue: T
}

var c = Color(red: 128, green: 80, blue: 200) // 인스턴스 생성

//let d: Color<Int> //  = Color(red: 128.0, green: 80.0, blue: 200.0) // Int , Double 별도의 형식으로 처리 됨 , Type 파라미터 자동 추론

//let arr: [Int] // 단축 문법
let arr: Array<Int>

let dict: Dictionary<String,Double>

 

  • 익스텐션으로 제네릭 타입 확장
  • 확장 대상 제한
extension Color where T == Int {  //제네릭 다시 쓰지 않는다. T로 선언한거 바꾸지 못함 , 모든 Color 에 적용됨 //Double인경우에는 추가 되지 않음 확장 대상 제한
    func getComponents() -> [T] {
        return [red, green, blue]
    }
}

let intColor =  Color(red: 1, green: 2, blue: 3)
intColor.getComponents() //INT 추론

let dblColor = Color(red: 1.0, green: 2.0, blue: 3.0)
//dblColor.getComponents() //Double 추론

  • Associated Types
    • 프로토콜 내에서 실제 형식으로 대체되는 연관 형식을 선언하는 방법
  • 제네릭 프로토콜
  • Associated Types
  • 연관 형식에 제약 추가
protocol QueueCompatible {
    associatedtype Element: Equatable //protocol에서 사용하는 placeholder
    func enqueue(value: Element) //ValueType 맞춰줘야함
    func dequeue() -> Element?
}

//MARK:typealias 를 통한 실제 형식 선언
class IntegerQueue: QueueCompatible {
    typealias Element = Int //element 바꿔 넣어 준다

    func enqueue(value: Int) {

    }

    func dequeue() -> Int? {
        return 0
    }
}

class DoubleQueue: QueueCompatible {
    func enqueue(value: Double) { //Double로 직접 넣어도 상관 없음 /실제는 Type alias 생략 많이 함

    }

    func dequeue() -> Double? {
        return 0
    }
}

출처 : 어서와! Swift는 처음이지?(Programmers)
728x90

댓글

Designed by JB FACTORY