Swift에서는 시그니처만 다르면 같은 이름의 함수를 여러 개 정의할 수 있어요. 이런 방식을 함수 오버로딩이라고 해요.
다음 기본 함수를 살펴봐요:
func add(_ x: Int, and y: Int, doubleResult: Bool) -> Int {
let sum = x + y
return doubleResult ? sum * 2 : sum
}
let twentySix = add(6, and: 7, doubleResult: true)
// => 26
Swift에서 이름이 같은 두 함수도 다음 조건 중 하나라도 해당하면 서로 다른 함수로 취급해요:
위의 원래 add 함수를 기준으로, 다음 오버로드들은 각각 서로 다른 함수이고 같은 프로그램 안에서 모두 사용할 수 있어요:
// 1. Different number of parameters
func add(_ x: Int, and y: Int) -> Int {
x + y
}
let eleven = add(5, and: 6)
// => 11
// 2. Different parameter type (Double instead of Int)
func add(_ x: Double, and y: Int, doubleResult: Bool) -> Double {
let sum = x + Double(y)
return doubleResult ? sum * 2 : sum
}
let twentySeven = add(6.5, and: 7, doubleResult: true)
// => 27.0
// 3. Different argument label (doubleThat instead of doubleResult)
func add(_ x: Int, and y: Int, doubleThat: Bool) -> Int {
let sum = x + y
return doubleThat ? sum * 2 : sum
}
let thirteen = add(6, and: 7, doubleThat: false)
// => 13
반환 타입만으로도 함수를 오버로딩할 수 있어요. 다만 이런 함수를 호출할 때는 컴파일러가 어느 오버로드를 의도했는지 알 수 있도록 타입 애너테이션이나 문맥을 함께 제공해야 해요:
func add(_ x: Int, and y: Int, doubleResult: Bool) -> Double {
let sum = Double(x + y)
return doubleResult ? sum * 2 : sum
}
// Ambiguous call (compiler cannot decide whether you want Int or Double):
// let thirty = add(6, and: 9, doubleResult: true)
// Resolved with an explicit type annotation:
let thirty: Double = add(6, and: 9, doubleResult: true)
// => 30.0
인자 레이블, 매개변수 타입, 매개변수 개수는 그대로 두고 내부 매개변수 이름만 바꾸는 것으로는 서로 다른 함수가 만들어지지 않아요. 컴파일러는 이것을 잘못된 중복 선언으로 봐요:
func add(_ w: Int, and y: Int, doubleResult: Bool) -> Int {
let sum = w + y
return doubleResult ? sum * 2 : sum
}
// Error: Invalid redeclaration of 'add(_:and:doubleResult:)'