> For the complete documentation index, see [llms.txt](https://choi-junsu.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://choi-junsu.gitbook.io/docs/dev/til/2022.09/09-05-mon.md).

# 09/05 (Mon)

### 코틀린 완벽 가이드 - 함수

#### 자바와 달리 코틀린에서의 함수 파라미터는 불변이다.

자바에서는 메서드 파라미터에 값이 가변이므로, 변경하지 못하게 할려면 final 지정을 해야 불변값으로 사용할 수 있지만, 코틀린은 파라미터를 불변 값으로 강제한다 (val, var 또한 파라미터 앞에 표시할 수 없다)

```kotlin
fun increment(n : Int) : Int {
    return n++ // Error: can't change immutable variable
}
```

#### 코틀린은 값에 의한 호출 의미론을 사용한다. (call by-value)&#x20;

함수 파라미터 값에 호출하는 쪽의 인자를 복사함을 의미한다. 호출 인자로 전달한 변수를 변경해도 호출된 함수 내부의 파라미터 값에는 영향이 없다는 뜻이다.\
\
하지만 파라미터가 참조(배열 타입 등)인 경우, 호출한 쪽의 데이터는 그대로 남아있고, 이 데이터에 대한 참조만 복사된다.

```kotlin
fun increment(a: IntArray): Int {
    return ++a[0]
}

fun main() {
    val a = intArrayOf(1, 2, 3)
    println(increment(a)) // 2
    println(a.cotentToString()) // [2, 2, 3]
}
```

#### 함수에 반환 타입은 타입추론이 가능하다.

타입추론이 가능하지만 Unit 타입을 제외하고 리턴타입을 명시해줘야 한다.\
함수 본문에 여러개의 return이 존재할 수있는데, 모든 반환 지점에 반환 타입을 알아내기 어려울 수 있기 때문이다.\
\
Unit 을 제외하고 리턴타입을 제외 할 수 있는 방법은 식이 본문(expression-body) 인 함수다.\
단일 식으로만 함수가 구현될 수 있으면 return 과 중괄호를 제외하고 함수를 작성할 수 있다.

```kotlin
fun circleArea(redius: Double) = PI * radius * redius  // return Double

// 중괄호({}) 와 식이 본문인 함수를 동시에 쓰게 되면 리턴 타입을 람다로 해석하기 때문에 원하는 결과를 얻지못한다.
fun circleArea(radius: Double) = { PI * radius * radius } // return () -> Double

// 2번예시에서 return 문을 작성하면 컴파일 에러가 발생한다.
fun circleArea(radius: Dobule) = {
    // 타입추론한 리턴타입은 ()->Double, 함수본문에서 return으로 보내는 값은 Double 타입이므로 에러발생
    return PI * radius * radius
}
```

> 문(statement) 과 식(expression) 의 차이는 무엇인가?
>
> `식`은 값을 만들어내며 다른식의 하위 요소로 계산에 참여 할 수 있다.\
> `문`은 자신을 둘러싸고 있는 가장 안쪽 블록의 최상위 요소로 존재하며, 아무런 값도 만들어 내지 않는다<br>
>
> ex)  자바에서는 if-else 는 statement 이다. 코틀린에서는 expression (값을 만들어 낼 수 있다) 으로 사용된다.
>
> ```kotlin
> fun....  {
>     // Java
>     int max;
>     if(p0 > p1) {
>         max = p0
>     } else {
>         max = p1
>     }
>
>     // Kotlin
>     val max = if(p0 > p1) p0 else p1
> }
> ```

#### 위치 기반 인자와 이름 붙은 인자

자바나 다른 언어에서는 위치 기반 인자를 널리 쓰고있다. 함수에 위치 기반 인자란 함수에 정의한 파라미터들에 순서대로 전달되는 식이다.\
코틀린에서는 위치 기반 인자도 사용가능하며, 이름 붙은 인자라고 불리는 방식도 제공한다. 파라미터 인자들에게 이름을 부여하며 순서와 상관없이 인자를 전달할 수 있다.

```kotlin
fun rectangleArea(width: Dobule, height: Double) {
    ...
}

fun main() {
    // 위치기반인자
    rectangleArea(100, 50) // 100: width, 50: height 순서대로 인자가 전달된다.
    // 이름붙은인자
    rectangleArea(height = 50, width = 100) // 함수에 정의한 파라미터명과 동일한 위치에 전달된다
}
```

위치 기반 인자와 이름 붙은 인자를 혼용해서 사용할 수도 있다. 코틀린 1.4 버전 이전에는 이름붙은 인자를 하나라도 사용하게되면 모든 인자들에도 이름을 붙여야 했다. 하지만 코틀린 1.4버전 이후에는 인자들에 위치만 같다면, 중간중간 이름붙은 인자를 사용할 수 있게 됐다. \
\
※ *원래 인자가 들어가야 하는 위치에 이룸 붙은 인자를 지정해야 정상처리되며, 그러지 않을 경우 위치기반인자 방에 어긋나거나 이미 할당된 인자를 할당하기 때문에 컴파일 에러가 발생한다.*

```kotlin
fun swap(a: Int, b: Int, c: Int) {
    ...
}

fun main() {
    swap(a = 1, 0, 3)        // 1.4버전이전에는 오류, 이후버전에서는 정상
    swap(a = 1, 0 , c = 3)   // 1.4버전이전에는 오류, 이후버전에서는 정상
    swap(a = 1, c = 3, 0)    // 컴파일 에러 - 위치 기반 인자 방식에 위배된다.
}
```

#### 자바 메서드와 동일하게 코틀린 함수도 오버로딩(Overloading) 이 가능하다.

오버로딩이란 같은 이름의 함수를 여러개 작성할 수 있음을 의미한다. 다만 컴파일러가 어떤 함수가 호출되었는지를 구분할 수 있도록 각 함수의 파라미터 타입이 달라야 한다.

*컴파일러 자바 오버로딩 해소 규칙*

> 1. 파라미터의 개수와 타입을 기준으로 호출할 수 있는 모든 함수를 찾는다.
> 2. 덜 구체적인 함수를 제외한다 - 규칙 1에서 선택한 후보 목록에서 어떤 함수의 파라미터 타입이 **다른 함수의**\
>    **파라미터 타입의 상위 타입인 경우 이 함수는 다른 함수보다 덜 구체적인 함수다**. 덜 구체적인 함수가 모두\
>    제외될 때까지 이 단계를 반복한다.
> 3. 후보가 하나로 압축되면 이 함수가 호출할 함수다. **후보가 둘 이상이면 컴파일 오류가 발생한다.**
