Search

Functions

Kotlin 함수는 fun 키워드를 사용하여 선언된다.
fun double(x: Int): Int { return 2 * x }
Kotlin
복사

함수 사용

함수는 표준 접근 방식을 사용하여 호출된다.
val result = double(2)
Kotlin
복사
멤버 함수를 호출할 때는 점 표기법을 사용한다.
Stream().read() // create instance of class Stream and call read()
Kotlin
복사

매개변수

함수 매개변수는 Pascal 표기법(name: type)을 사용하여 정의된다.
매개변수는 쉼표로 구분하고 각 매개변수는 명시적으로 입력해야 한다.
fun powerOf(number: Int, exponent: Int): Int { /*...*/ }
Kotlin
복사
함수 매개변수를 선언할 때 끝에 쉼표를 사용할 수 있다.
fun powerOf( number: Int, exponent: Int, // trailing comma ) { /*...*/ }
Kotlin
복사

기본 인수

함수 매개변수는 기본값을 가질 수 있으며 이는 해당 인수를 건너뛸 때 사용된다.
fun read( b: ByteArray, off: Int = 0, len: Int = b.size, ) { /*...*/ }
Kotlin
복사
기본값은 타입에 = 를 추가하여 설정된다.
오버라이딩 메서드는 항상 기본 메서드의 기본 매개변수 값을 사용한다. (자식 클래스에서 설정 불가능)
기본 매개변수 값이 있는 메서드를 오버라이딩할 때는 기본 매개변수 값을 시그니처에서 생략해야 한다.
open class A { open fun foo(i: Int = 10) { /*...*/ } } class B : A() { override fun foo(i: Int) { /*...*/ } // No default value is allowed. }
Kotlin
복사
기본 매개변수가 기본값이 없는 매개변수보다 앞에 오는 경우 명명된 인수로 함수를 호출하여야만 기본값을 사용할 수 있다.
fun foo( bar: Int = 0, baz: Int, ) { /*...*/ } foo(baz = 1) // The default value bar = 0 is used
Kotlin
복사
기본 매개변수 뒤에 있는 마지막 인수가 람다인 경우 명명된 인수로 전달하거나 괄호 밖으로 전달할 수 있다.
fun foo( bar: Int = 0, baz: Int = 1, qux: () -> Unit, ) { /*...*/ } foo(1) { println("hello") } // Uses the default value baz = 1 foo(qux = { println("hello") }) // Uses both default values bar = 0 and baz = 1 foo { println("hello") } // Uses both default values bar = 0 and baz = 1
Kotlin
복사

명명된 인수

함수를 호출할 때 하나 이상의 인수에 이름을 지정할 수 있다.
이는 함수에 인수가 많고 인수와 값을 연관시키기 어려울 때 특히 부울이나 null 값인 경우 유용할 수 있다.
함수 호출에서 명명된 인수를 사용하면 나열된 순서를 자유롭게 변경할 수 있다.
기본값을 사용하려면 이러한 인수를 모두 제외하면 된다.
// 함수 예시 fun reformat( str: String, normalizeCase: Boolean = true, upperCaseFirstLetter: Boolean = true, divideByCamelHumps: Boolean = false, wordSeparator: Char = ' ', ) { /*...*/ } // 모든 인수의 이름을 지정하지 않은 경우 reformat( "String!", false, upperCaseFirstLetter = false, divideByCamelHumps = true, '_' ) // 기본값이 있는 인수를 건너뛰는 경우 reformat("This is a long String!") // 특정 인수를 건너뛰는 경우 (모든 후속 인수를 명명해야함) reformat("This is a short String!", upperCaseFirstLetter = false, wordSeparator = '_')
Kotlin
복사
spread 연산자 * 를 사용하여 이름이 포함된 가변 개수의 인수를 전달할 수 있다.
fun foo(vararg strings: String) { /*...*/ } foo(strings = *arrayOf("a", "b", "c"))
Kotlin
복사
Java 함수를 호출할 땐 명명된 인수를 사용할 수 없기 때문에 순서대로 인자를 전달해야 한다.

Unit 반환 함수

함수가 유용한 값을 반환하지 않으면 반환 유형은 Unit이다.
Unit은 값이 하나뿐인 타입이다.
이 값은 명시적으로 반환할 필요가 없다.
fun printHello(name: String?): Unit { if (name != null) println("Hello $name") else println("Hi there!") // `return Unit` or `return` is optional }
Kotlin
복사
Unit 반환 타입 선언을 생략할 수 있다.
fun printHello(name: String?) { ... }
Kotlin
복사

단일 표현식 함수

함수 본문이 단일 표현식으로 구성된 경우 중괄호를 생략하고 본문을 = 뒤에 지정할 수 있다.
fun double(x: Int): Int = x * 2
Kotlin
복사
컴파일러가 이를 유추할 수 있는 경우 반환 타입을 명시적으로 선언하지 않아도 된다.
fun double(x: Int) = x * 2
Kotlin
복사

명시적 반환 타입

블록 본문이 있는 함수는 반환 타입을 항상 명시적으로 지정해야 한다.
다만 Unit 반환이 의도된 경우에는 반환 타입을 지정하는 것이 선택 사항이다.
Kotlin은 블록 본문이 있는 함수의 반환 타입을 유추하지 않는다.
이러한 함수는 본문에서 복잡한 제어 흐름을 가질 수 있고 반환 타입이 코드 작성자 또는 컴파일러에게 명확하지 않을 수 있기 때문이다.

가변 개수의 인수

함수의 매개변수에 vararg 수정자를 붙여서 가변 개수의 인자를 받을 수 있다.
하나의 매개변수만 vararg로 지정할 수 있다.
vararg 매개변수가 매개변수 목록의 마지막이 아닐 경우 이후 매개변수 값은 명명된 인수로 전달해야 한다.
함수 타입인 경우에는 괄호 밖에서 람다를 전달하여 사용할 수 있다.
fun <T> asList(vararg ts: T): List<T> { val result = ArrayList<T>() for (t in ts) // ts is an Array result.add(t) return result }
Kotlin
복사
이 경우 함수에 가변 개수의 인자를 전달할 수 있다.
배열의 내용을 함수에 전달하고 싶다면 스프레드 연산자 * 를 사용한다.
// 인자를 개별적으로 전달하는 경우 val list = asList(1, 2, 3) // 배열의 내용을 함수에 전달하는 경우 val a = arrayOf(1, 2, 3) val list = asList(-1, 0, *a, 4) // 원시 타입 배열의 내용을 함수에 전달하는 경우 val a = intArrayOf(1, 2, 3) // IntArray is a primitive type array val list = asList(-1, 0, *a.toTypedArray(), 4)
Kotlin
복사
함수 내에서 vararg 타입의 매개변수는 Array<T>로 보인다.
예제에서는 ts 변수가 Array<out T> 타입으로 선언되어 있다.

중위 표기법

infix 키워드로 표시된 함수는 중위 표기법(호출 시 점과 괄호 생략)을 사용하여 호출할 수 있다.
다음과 같은 요구사항을 충족해야 한다.
멤버 함수나 확장 함수여야 한다.
매개변수가 하나여야 한다.
매개변수는 가변 인자를 허용하지 않아야 하며 기본값이 없어야 한다.
infix fun Int.shl(x: Int): Int { ... } // 인픽스 표기법을 사용한 함수 호출 1 shl 2 // 이는 다음과 같습니다: 1.shl(2)
Kotlin
복사
infix 함수 호출은 산술 연산자, 타입 캐스트, rangeTo 연산자보다 낮은 우선순위를 가진다.
'1 shl 2 + 3' 은 '1 shl (2 + 3)' 과 같습니다. '0 until n * 2' 는 '0 until (n * 2)' 와 같습니다. 'xs union ys as Set<*>' 는 'xs union (ys as Set<*>)' 와 같습니다.
Kotlin
복사
infix 함수 호출은 &&와 ||, is 및 in 체크 그리고 몇몇 다른 연산자보다 높은 우선순위를 가진다.
'a && b xor c' 는 'a && (b xor c)' 와 같습니다. 'a xor b in c' 는 '(a xor b) in c' 와 같습니다.
Kotlin
복사
infix 함수는 항상 수신자와 매개변수가 모두 명시되어야 한다.
현재 수신자에서 메서드를 호출할 때 중위 표기법을 사용하는 경우 명시적으로 this를 사용해야 한다.
class MyStringCollection { infix fun add(s: String) { /*...*/ } fun build() { this add "abc" // 올바름 add("abc") // 올바름 // add "abc" // 잘못됨: 수신자가 명시되어야 함 } }
Kotlin
복사

함수 범위

Kotlin 함수는 파일의 최상위 수준에서 선언할 수 있으므로 함수를 보관하기 위한 클래스를 만들 필요가 없다.
Kotlin 함수는 최상위 수준 함수 외에도 멤버 함수 및 확장 함수로 로컬에서 선언할 수 있다.

지역 함수

Kotlin은 다른 함수 내부의 함수인 지역 함수를 지원한다.
지역 함수는 외부 함수의 지역 변수에 엑세스할 수 있다.
fun dfs(graph: Graph) { val visited = HashSet<Vertex>() fun dfs(current: Vertex) { if (!visited.add(current)) return for (v in current.neighbors) dfs(v) } dfs(graph.vertices[0]) }
Kotlin
복사

멤버 함수

멤버 함수는 클래스나 객체 내부에 정의된 함수이다.
class Sample { fun foo() { print("Foo") } }
Kotlin
복사
멤버 함수는 점 표기법으로 호출된다.
Sample().foo() // creates instance of class Sample and calls foo
Kotlin
복사

제네릭 함수

함수는 제네릭 매개변수를 가질 수 있으며 이는 함수 이름 앞에 꺾쇠 괄호를 사용하여 지정된다.
fun <T> singletonList(item: T): List<T> { /*...*/ }
Kotlin
복사

꼬리 재귀 함수

Kotlin은 tail recursion이라고 알려진 함수형 프로그래밍 스타일을 지원한다.
이 스타일을 사용하면 일반적으로 루프를 사용할 알고리즘을 재귀 함수로 대체할 수 있으며 스택 오버플로우의 위험 없이 동작할 수 있다.
함수가 tailrec 수정자로 표시되고 필요한 형식 조건을 충족하면 컴파일러는 재귀를 최적화하여 빠르고 효율적인 루프 기반 버전으로 변환한다.
// 전통적인 스타일의 코드 val eps = 1E-10 private fun findFixPoint(): Double { var x = 1.0 while (true) { val y = Math.cos(x) if (Math.abs(x - y) < eps) return x x = Math.cos(x) } } // tail resursion 스타일의 코드 val eps = 1E-10 tailrec fun findFixPoint(x: Double = 1.0): Double = if (Math.abs(x - Math.cos(x)) < eps) x else findFixPoint(Math.cos(x))
Kotlin
복사
tailrec 수정자를 사용하려면 함수가 자신을 호출할 때 그것이 마지막 작업이어야 한다.
재귀 호출 이후에 더 많은 코드가 있거나 try/catch/finally 블록 내에서 호출하거나 열린 함수에서 사용할 수 없다.