본문 바로가기

Swift

[Swift] 함수(Function)

728x90

함수(Function) vs 메서드(Method)

  • 메서드(Method)와 동일한데 상황이나 위치에 따라 이름을 달리한 것일 뿐입니다.
    • 함수(Function) : 모듈 전체에서 전역으로 사용하는 기능
    • 메서드(Method) : 클래스, 구조체, 열거형 등 특정 타입에 연관되어 사용하는 기능
  • Swift에서 함수는 오버라이딩과 오버로딩 모두 가능합니다.

함수 정의하기

  1. func 키워드로 함수를 정의할 수 있어요.
  2. → 로 반환값의 데이터타입을 명시할 수 있어요.
  3. return 키워드로 데이터를 반환해요.
func 함수이름(매개변수...) -> 반환타입 {
	코드
	return 반환값(있는 경우)
}

다양한 형태의 함수들 보기 👀

  • 매개변수가 없는 함수 정의
// 매개변수가 없는 함수를 정의하고 싶을 때
func helloSophie() {
    print("Hello Sophie!")
}
// 호출
print("매개변수가 없는 helloSophie() 함수 호출")
helloSophie()
  • 매개변수가 있을 때
// 매개변수가 있을 때
func sayHello(name: String) {
    print("Hello \\(name)")
}
// 호출
print("매개변수가 있는 sayHello(name:) 함수 호출")
sayHello(name: "Sophie!")
  • 매개변수의 전달인자 레이블을 지정해줄 수 있어요.
    • 의미 파악이 좀 더 쉬워져요.
    • 전달인자가 바뀌면 함수 이름이 바뀌기 때문에 중간에 수정된 경우 컴파일 에러가 발생될 수 있어요.
    • 전달인자 레이블을 생략하고 싶을 때에는 와일드카드 식별자로 대체할 수 있어요.
// 전달인자 레이블을 지정해주면 의미 파악이 좀더 쉬워져요.
// 전달인자가 바꾸면 함수 이름이 바뀌는 것이기 때문에 중간에 수정된 경우 컴파일 에러가 발생해요.

func sayHello(to name: String) {
    print("Hello \\(name)")
}

// 호출
print("매개변수의 전달인자 레이블을 지정해준 sayHello(to name:) 함수 호출")
sayHello(to: "Sophie")

print("-----------------------------")

// 전달인자 레이블을 생략하고 싶을 때는 와일드카드 식별자로 표현해주면 됩니다.
func sayHello(to name: String, with count: Int) {
    for _ in 0..<count {
        print("Hello \\(name)")
    }
}

// 호출
print("전달인자 레이블을 생략하지 않았을 때 sayHello(to name:, with count:) 함수 호출")
sayHello(to: "Sophie", with: 2)

print("-----------------------------")

// 오버로딩
func sayHello(to name: String, _ count: Int) {
    for _ in 0..<count {
        print("Hello \\(name)")
    }
}

// 호출
print("전달인자 레이블을 생략했을 때 sayHello(to name:, _:) 함수 호출")
sayHello(to: "Sophie", 2)
  • 매개변수의 기본값을 줄 수 있어요.
    • 함수를 정의할 때 매개변수의 기본값을 지정하면 함수를 호출할 때 매개변수를 통해 값이 전달되지 않으면 지정한 기본값을 사용합니다.
// 매개변수에 기본값이 지정된 경우 
func sayMyName(_ count: Int = 3) {
    for _ in 0..<count {
        print("Hello I'm Sophie!")
    }
}

// 호출
print("매개변수의 기본값이 지정된 sayMyNAme(_ count:) 함수 호출")
sayMyName() // 매개변수에 아무것도 전달하지 않았으므로 기본값인 3으로 실행됨

print("기본값이 아닌 값 전달")
sayMyName(5) // 기본값이 아닌 원하는 값을 매개변수를 통해 전달
  • 가변 매개변수를 가지는 함수를 만들 수 있어요.
    • 매개변수의 갯수가 몇개가 될지 모를 때 가변 매개변수를 사용할 수 있어요.
    • 가변 매개변수로 입력된 값들은 배열처럼 사용할 수 있습니다.
    • 가변 매개변수는 함수마다 딱 하나만 가질 수 있어요.
// 가변 매개변수를 갖는 함수
func printAnyString(with anything: String...) {
    var result: String = ""
    for str in anything {
        result.append("\\(str) ")
    }
    
    print(result)
}

printAnyString(with: "A", "B", "C", "D", "Wow", "!")
  • 참조를 전달하고 싶을 때에는 입출력 매개변수를 사용합니다.
    • 보통 함수 전달인자로 전달될 때 값을 복사해서 전달되는데, 값이 아닌 참조(주소)를 전달하고 싶을 때에는 입출력 매개변수를 사용해요.
    • inout 키워드를 사용해 참조 타입 매개변수임을 나타내요.
    • 이 방법은 외부에 영항을 줄 수도 있기 때문에 함수형 프로그래밍 패러다임에서는 지양하는 패턴입니다.
    • 기본값을 가질 수 없고, 가변 매개변수로도 사용할 수 없습니다.
// 참조 타입 매개변수 테스트 해보기
// inout

// Function that swaps the values of two integers using inout
func swapValues(_ a: inout Int, _ b: inout Int) {
    let temp = a
    a = b
    b = temp
}

// Example usage
var x = 5
var y = 10

print("Before swapping: x = \\(x), y = \\(y)")

// Call the function with inout parameters
swapValues(&x, &y)

print("After swapping: x = \\(x), y = \\(y)")

함수를 데이터타입으로 사용할 수 있어요.

  • 함수는 일급객체이므로 하나의 데이터타입처럼 사용할 수 있어요.
  • (매개변수 타입…) → (반환타입)
// 데이터타입으로써의 함수
// 이 함수의 타입은 () -> () 이에요.
// (Void) -> () / () -> Void로도 표현할 수 있어요.
func test1() {
    
}

// 이 함수의 타입은 (String, Int) -> Void 이에요.
func test2(a: String, b: Int) {
    
}

// 이 함수의 타입은 (String) -> String 이에요.
func test3(c: String) -> String {
    return c
}
  • 함수를 함수의 전달인자로 쓸 수 있어요.
    1. (Int, Int) → Int 타입을 정의합니다.
    2. 두 숫자를 더하기(add) 또는 빼기(multiply) 하는 (Int, Int) → Int 타입의 함수를 정의합니다.
    3. 함수와 두 숫자를 전달하는 함수(calculate) 함수를 정의합니다.
    4. calculate 함수를 호출해 더하기 또는 곱하기 연산의 결과를 계산합니다.
// 함수 타입 정의
typealias MathFunction = (Int, Int) -> Int

// 두 숫자를 더하는 함수
func add(_ a: Int, _ b: Int) -> Int {
    return a + b
}

// 두 숫자를 곱하는 함수
func multiply(_ a: Int, _ b: Int) -> Int {
    return a * b
}

// 함수를 전달하는 함수
func calculate(_ operation: MathFunction, _ a: Int, _ b: Int) -> Int {
    return operation(a, b)
}

// 함수를 인자로 전달하여 사용
let sumResult = calculate(add, 3, 5)
print("Sum result: \\(sumResult)")

let productResult = calculate(multiply, 2, 4)
print("Product result: \\(productResult)")
  • 중첩 함수
    • 함수를 함수의 반환값으로 사용할 수 있어요.
    • 굳이 모듈 전역에서 사용할 필요가 없는 함수의 사용 범위를 한정해서 함수 안쪽으로 배치해 중첩 함수로 구현하고, 필요할 때만 외부에서 사용할 수 있도록 반환값을 갖는 함수로 정의할 수 있어요.
// Function that returns a function based on a condition
func chooseFunction(isAddition: Bool) -> (Int, Int) -> Int {
    // Define two functions for addition and multiplication
    func add(_ a: Int, _ b: Int) -> Int {
        return a + b
    }
    
    func multiply(_ a: Int, _ b: Int) -> Int {
        return a * b
    }
    
    // Return the appropriate function based on the condition
    return isAddition ? add : multiply
}

// Example usage
let addFunction = chooseFunction(isAddition: true)
let multiplyFunction = chooseFunction(isAddition: false)

let result1 = addFunction(3, 4) // Result is 7
let result2 = multiplyFunction(3, 4) // Result is 12

print("Result 1: \\(result1)")
print("Result 2: \\(result2)")
  • 반환값을 무시할 수 있는 함수
    • 함수의 반환값이 꼭 필요하지 않을 때 @discardableResult 키워드를 함수와 함께 선언해주면 되요.
class Calculator {
    // Using @discardableResult to suppress the warning
    @discardableResult
    func add(_ a: Int, _ b: Int) -> Int {
        return a + b
    }
}

let calculator = Calculator()

// Calling the function and ignoring the result (no compiler warning)
calculator.add(3, 4)

 

728x90