🔎오버 로딩
이름이 같은 함수를 여러 개 작성할 수 있는 기능
🛑주의할 점
컴파일러가 어떤 함수를 호출해야 할지 구분할 수 있도록 오버 로딩한 함수의 파라미터 타입을 구분해줘야 한다.
⭕예를 들어 다음 두 함수는 올바른 오버 로딩을 구성한다.
fun readInt()= readLine()!!.toInt()
fun readInt(radix : Int)= readLine()!!.toInt(radix)
❌다음 두 함수는 컴파일 오류가 발생한다.
왜일까?
두 함수는 반환 값만 다르고 파라미터의 타입은 같기 때문에 컴파일 오류가 발생하는 것이다!
이렇게 컴파일러는 다음과 같은 오버 로딩 해소 규칙을 따른다.
- 파라미터의 개수와 타입을 기준으로 호출할 수 있는 모든 함수를 찾는다.
- 덜 구체적인 함수를 제외시킨다. 규칙 1에서 선택한 후보 목록에서 어떤 함수의 파라미터 타입이 다른 함수의 파라미터 타입의 상위 타입인 경우 이 함수는 다른 함수보다 덜 구체적인 함수다.
- 덜 구체적인 함수가 모두 제외될 때까지 이 단계를 반복한다.
- 후보가 하나로 압축되면 이 함수가 호출할 함수이다. [후보가 둘 이상이면 컴파일 오류가 발생한다.]
오버 로딩 조건을 충족한 네 가지 함수가 있다.
- mul(1,2)는 1번과 4번에서 선택될 수 있다.
- 하지만 Any가 Int의 상위 타입이기 때문에 덜 구체적인 함수로 인식되어서 1번을 컴파일러는 1번을 선택한다.
- mul(1,2L)은 mul함수 중에서 (Long, Int)를 받을 수 있는 함수가 없기 때문에 컴파일러 오류가 발생한다.
- mul(1L, 2)은 (Long, Int)를 받을 수 있는 함수는 4번뿐이기에 4번을 선택한다.
- mul("0",3)은 3번과 4번에서 선택될 수 있다.
- 하지만 Any가 String에 상위 타입이기 때문에 덜 구체적인 함수로 인식되어서 3번을 선택한다.
- 여기서 만약 4번 함수를 호출하고 싶을 경우에는 as 타입 캐스팅 연산자를 사용해 인자를 상위 타입으로 명시적으로 변환해야 한다.
- mul("0" as Any, 3)은 String을 강제로 Any로 형 변환했기 때문에 (Any, Int)를 호출할 수 있는 4번 함수가 선택될 것이다.
- 이렇게 상위 타입형 변환을 통해서 덜 구체적인 함수도 호출할 수 있다.
사용자가 함수 인자 중 일부를 생략해 미리 정해진 디폴트 값을 사용할 수 있게 하고자 하는 메서드를 오버 로딩해야 하는 경우가 있다.
fun readInt()= readLine()!!.toInt()
fun readInt(radix : Int)= readLine()!!.toInt(radix)
두 함수 모두 입력 문자열을 정수로 변환하는 함수이지만, 첫 번째 함수는 10진법으로 문자열을 파싱 하고, 두 번째 함수는 다양한 진법으로 문자열을 파싱 한다.
fun readInt()=readInt(10)
위와 같이 첫 번째 함수는 두 번째 함수를 이용해서 작성할 수도 있다.
🔎디폴트 파라미터란?
파라미터 뒤에 변수 초기화 식을 추가하면 원하는 파라미터에 디폴트 값을 제공할 수 있다.
예시는 다음과 같다.
fun readInt(radix : Int =10)=readLine()!!.toInt(radix)
디폴트 파라미터 뒤에 디폴트가 지정되어 있지 않은 파라미터가 있는 경우, 디폴트 파라미터를 지정하지 않고 함수를 호출하는 유일한 방법은 이름 붙은 인자를 사용하는 것뿐이다.
fun aa(from : Int = Int.MIN_VALUE, to:Int=Int.MAX_VALUE,what:Int):Int=Math.max(from,Math.min(to,what))
여기서 내가 aa를 호출하고 싶다면 꼭!!!! what을 파라미터에 넣어줘야 한다.
나머지 from과 to는 이미 디폴트 파라미터 이므로 값이 없다면 디폴트 파라미터의 값이 들어가게 될 것이다.
하지만 what을 우리가 인자로 주지 않는다면 함수는 호출되지 않을 것이다.
위 그림은 from과 to에만 인자를 전달해줬다. 당연히 오류가 난다. what에 인자가 없기 때문이다.
하지만 여기서 to에 인자를 안 주고, what에 이름 붙은 인자를 이용해서 파라미터를 넘겨주니까 오류가 발생하지 않는 것을 볼 수 있다.
당연히 what에만 인자를 줘도 오류가 발생하지 않는다.
💡디폴트 값이 있는 파라미터를 함수 인자 목록 뒤쪽에 몰아두는 쪽이 좋은 코딩 스타일이다!!
💡인자가 많은 함수가 덜 구체적인 함수이다.
예를 들어 설명하겠다.
위 사진과 같이 3가지 함수가 있을 때
mul(10,20)을 호출하면 어떤 함수가 호출될까?
정답은 1번이다.
왜냐하면 mul(10,20)은 1번과 3번을 호출할 수 있다.
하지만 3번은 1번 함수에서 c를 추가한 함수. 즉 1번 함수를 확장한 함수라고 할 수 있다.
따라서 1번 함수보다 덜 구체적이라고 컴파일러가 인식해서 컴파일러는 1번을 선택하는 것이다.
✔정리
오버 로딩은 같은 함수들 사이에서 반환값과 파라미터의 타입 모두 달라야 성립한다.
오버로딩은 여러 가지 함수들 중에서 구체적인 함수를 선택한다.
여기서 덜 구체적인 함수란 파라미터 타입의 상위 타입일 때, 인자가 더 많은 경우 덜 구체적인 함수라고 인식된다.
구체적인 함수가 여러 가지라면 그것은 컴파일 오류를 발생시킨다.
'Skils > Kotlin' 카테고리의 다른 글
[Kotlin] 조건문 if & 범위,진행,연산 (0) | 2022.08.17 |
---|---|
[Kotlin] vararg(가변인자) (0) | 2022.08.12 |
[Kotlin] 함수란? (0) | 2022.08.07 |
[Kotlin] array(배열) (0) | 2022.08.07 |
[Kotlin] char & String (0) | 2022.07.30 |