🔥 제네릭 함수

348자
4분

제네릭 함수는 어떤 타입과도 함께 동작할 수 있는 유연한 함수입니다. 앞서 살펴본 swapTwoInts(_:_:) 함수의 제네릭 버전인 swapTwoValues(_:_:) 함수를 살펴보겠습니다:

func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
    let temporaryA = a // 임시 변수에 a의 값을 저장합니다.
    a = b // b의 값을 a에 할당합니다.
    b = temporaryA // 임시 변수에 저장된 a의 원래 값을 b에 할당합니다.
}
swift

swapTwoValues(_:_:) 함수의 본문은 swapTwoInts(_:_:) 함수의 본문과 동일합니다. 그러나 swapTwoValues(_:_:) 의 첫 번째 줄은 swapTwoInts(_:_:) 와 약간 다르죠. 첫 번째 줄을 비교해 보겠습니다:

func swapTwoInts(_ a: inout Int, _ b: inout Int)
func swapTwoValues<T>(_ a: inout T, _ b: inout T)
swift

제네릭 버전의 함수는 실제 타입 이름(Int, String, Double 등) 대신 플레이스홀더 타입 이름(T)을 사용합니다. 플레이스홀더 타입 이름은 T 가 무엇이어야 하는지에 대해 아무것도 말해주지 않지만, abT 가 나타내는 것이 무엇이든 간에 같은 타입 T 이어야 한다는 것을 알려줍니다. swapTwoValues(_:_:) 함수가 호출될 때마다 T 대신 사용할 실제 타입이 결정됩니다.

제네릭 함수와 일반 함수의 또 다른 차이점은 제네릭 함수의 이름(swapTwoValues(_:_:)) 뒤에 꺾쇠 괄호(<T>) 안에 플레이스홀더 타입 이름(T)이 있다는 것입니다. 대괄호는 Swift에게 TswapTwoValues(_:_:) 함수 정의 내에서 플레이스홀더 타입 이름이라는 것을 알려줍니다. T 는 플레이스홀더이기 때문에 Swift는 T 라는 실제 타입을 찾지 않습니다.

이제 swapTwoValues(_:_:) 함수는 swapTwoInts 와 같은 방식으로 호출할 수 있지만, 두 값이 서로 같은 타입인 한 모든 타입의 두 값을 전달할 수 있습니다. swapTwoValues(_:_:) 가 호출될 때마다 T 에 사용할 타입은 함수에 전달된 값의 타입에서 추론됩니다.

아래의 두 예제에서 T 는 각각 IntString 으로 추론됩니다:

var someInt = 3
var anotherInt = 107
swapTwoValues(&someInt, &anotherInt)
// someInt는 이제 107이고, anotherInt는 이제 3입니다.
 
 
var someString = "hello"
var anotherString = "world"
swapTwoValues(&someString, &anotherString)
// someString은 이제 "world"이고, anotherString은 이제 "hello"입니다.
swift

제네릭 함수를 사용하면 코드 중복을 줄이면서도 함수의 유연성을 높일 수 있습니다. 예를 들어, 정수뿐만 아니라 문자열, 부동 소수점 수 등 다양한 타입의 값을 교환하는 데 swapTwoValues(_:_:) 함수를 사용할 수 있죠.

다음 도표는 제네릭 함수의 장점을 잘 보여줍니다:

lecture image

제네릭은 Swift 프로그래밍의 강력한 기능 중 하나로, 코드의 재사용성과 유지보수성을 크게 향상시켜 줍니다. 제네릭 함수를 잘 활용하면 더 간결하고 표현력 있는 코드를 작성할 수 있을 것입니다.