본문 바로가기
iOS/Swift

[iOS/Swift] 매개변수는 사실 상수였다?! (함수를 호출하는 2가지 방법)

by iosdevlime 2022. 11. 17.

지난 포스팅에서 이어지는 내용입니다.

 

함수를 처음 강의와 책에서 접했을 때,

매개변수 파트에 매우 집중되어 있다!? 란 느낌적인 느낌을 받았습니다.

 

함수를 잘~다루기 위해선 짚고 넘어가야 할 필요가 있으므로, 

매개변수에 대해 좀더 DEEP 하게 살펴보도록 하겠습니다.

 

 

 


 

 

 

 

변수인 매개변수

함수에서 사용되는 모든 매개변수는, 기본적으로 변하지 않는 상수이다

 

상수(Constant)는 값을 수정할 수 없는 고유의 키워드였지요..?

매개변수 또한, 이러한 상수로 취급됩니다!

 

 

예시코드를 통해 빠르게 살펴보자면,,

  • inch단위의 길이와 너비를 centimeter 단위로 변환하고, 곱하여 면적을 구하는 함수
func calculateArea (length: Double, width: Double) -> Double {
			// 매개변수로 높이, 넓이를 설정하고..
                    
// 사용자가 입력하는 각각의 값에 2.54를 곱하는 기능코드를 추가!                    
    length = length * 2.54
    width = width * 2.54

// 반환값은 위에서 업데이트 된 높이와 넓이를 곱하도록 설정
    return length * width
}

 

만약, 함수 내에서 매개변수의 값을 변경하는 연산을 실행할 경우,

아래와 같은 컴파일 오류가 발생합니다.

 

length, width는 상수이므로, 변경할 수 없다!
length, width는 상수이므로, 변경할 수 없다!

 

 

 

 

 

 

섀도 복사본 (Shadow Copy)

  • 매개변수를 직접 수정하지 않고, 새로운 변수값(섀도 복사본)으로 복사하여 변경할 수 있습니다.
    • 함수 내부에서 직접 매개변수를 건드리지 않고, 새로운 변수를 생성하여 할당합니다.
    • 매개변수가 할당된 새로운 변수기능코드를 추가합니다.
func calculateArea (length: Double, width: Double) -> Double {
    
    // 섀도 변수인 lengthShadow, widthShadow 생성 후 매개변수 할당
    var lengthShadow = length
    var widthShadow = width
    
    // 기능을 부여하는 코드 또한 섀도 변수에 연산을 실시
    lengthShadow = lengthShadow * 2.54
    widthShadow = widthShadow * 2.54

    return lengthShadow * widthShadow
}

// 호출할땐? 그대로 매개변수(인자)로서 할당할 수 있다!
calculateArea(length: 10, width : 5) // 322.58

 

 

 


 

 

 

Call by Value, Call by Reference

값을 복사(Call by Value)하거나, 혹은 직접 참조(Call by Reference)하거나의 차이

 

앞서 살펴본 섀도 복사본 은,

함수의 구성요소 중 값이 변하지 않는 상수, '매개변수'를

새롭게 복사(Copy)하여 기능을 부여하는 방식이었다면,

 

 

뒤에 언급할 예정인 In-Out Parameters(입출력 매개변수)는 

'Copy in, Copy out' 형태로

값을 참조(Reference)하는 방식으로 차이가 있습니다.

 

 

이 둘의 차이를 확인하기 위해

예시 코드를 추가적으로 다뤄보겠습니다.

 

 

(예시) 배열을 미리 선언 후, 함수에 배열을 호출하여 값을 확인

  • 닉네임으로 구성된 배열의 값 중, 2번째 값을 임의의 닉네임으로 바꾸는 함수
// 3명의 닉네임으로 구성된 someIntArr 생성
var someIntArr: [String] = ["Lime", "Jason", "Kim"]


// 특정 배열의 값 중, 2번째 값을 'kate'로 변경하는 함수
func shadowCopy(_ arr: [String]) {
    
    var shadowArr: [String] = arr
    
    shadowArr[1] = "Kate"
    
}

// 함수에 미리 선언한 someIntArr를 호출한다면?
shadowCopy(someIntArr)

// 안타깝지만, 값이 바뀌질 않는다.
print(someIntArr[1]) // Jason

 

??

왜 함수가 제대로 작동하지 않았을까요?

: shadowArr이란 매개변수의 복사(Copy)을 이용했기 때문입니다!

 

 

 

 

Call by Value

  • someIntArr의 2번째 배열이 shadowCopy 함수에 의해 변경되지 않았습니다.
    • 'Jason' 에서 'Kate'로 변경되지 않는 이유는 다음과 같습니다.

 

Call by Value 예시코드


 

  • shadowCopy 함수는 내부적으로는 섀도 복사본에 의해 정상적으로 작동합니다.
    • 다만, 변경하고자 했던 someInArr 값이 내부로 직접 전달되지 않습니다.
    • 따라서, 해당 값의 업데이트는 발생되지 않습니다.
  • 이와 같은 방식을 Call by Value, '값에 의한 호출' 이라고 합니다.

 

 

 

 

Call by Reference

  • 앞선 내용과 반대로, 함수를 활용해 특정 값을 업데이트 할 수도 있습니다!
  • 이와 같은 방식을 In-Out Parameters(입출력 매개변수) 라고 합니다. 
    • 복사본 X
    • 매개변수 자체를 참조(Reference)
  • 사용방법은 다음과 같습니다.
    • 함수의 매개변수 타입 앞에 inout 키워드 작성
    • 호출 시, 데이터 값 앞에 &(엠퍼샌드) 키워드를 작성하여 참조하기

 

(예시) 배열을 미리 선언 후, in-out 매개변수를 활용하여 호출 시 데이터 변경여부 확인

  • 닉네임으로 구성된 배열의 값 중, 2번째 값을 임의의 닉네임으로 바꾸는 함수
// 3명의 닉네임으로 구성된 someIntArr 생성
var someIntArr: [String] = ["Lime", "Jason", "Kim"]


// 특정 배열의 값 중, 2번째 값을 'kate'로 변경하는 함수
// 하지만! 복사값을 쓰지 않고, 매개변수의 타입 앞에 'inout' 키워드를 작성한다.
func shadowCopy(_ arr: inout [String]) {
    
    arr[1] = "Kate"
    
}

// 함수에 미리 선언한 someIntArr를 호출하는데,
// 여기서, 호출하는 데이터 앞에 엠퍼센트(&)를 붙여
// 함수 내부에서 발생하는 기능을 참조한다는 것을 알림
shadowCopy(&someIntArr)

// 그렇게 되면, someIntArr의 배열값이 바뀌게 됨
print(someIntArr[1]) // "Kate"

 


 

Call by Value, Call by Reference 개념의 경우

추후 포스팅 하게 될 클래스(Class), 구조체(Struct) 파트에서도 다룰 예정입니다.

 

이번 함수 파트에서 다루고 있는 매개변수와 관련하여

  • 섀도 복사본(Shadow Copy)
  • 입출력 매개변수(In-Out Parameters)

이렇게 2가지 개념만 파악하고 넘어가시길 바랍니다.

댓글