[Kotlin] 함수(function)
1. If
fun getGrade(score : Int) : String {
return if (score >= 90) {
"A"
} else if (score >= 80) {
"B"
} else {
"C"
}
}
fun validateScore(score : Int) : String {
if (score !in 0...100) {
throw IllegalArgumentException("not valid score range")
}
}
삼항연산자
- 코틀린에는 삼항연산자가 존재하지 않는다
- if식의 return을 사용해 상쇄할 수 있다
fun renamePackage(fullName : String, newName : String) : String {
val i = fullName.lastIndexOf('.')
val prefix = if (i >= 0) fullName.substring(0. i+1) else return newName
return prefix + newName
}
2. When
- Kotlin에서는 Switch-case가 사라지고 대신에 When이 생김
- 자바의 switch-case문과는 달리 풀스루(full-through)를 하지 않는다
- 코틀린은 조건을 만족하는 것만 실행한다
fun getGrade(score : Int) : String {
return when (score/10) {
9 -> "A"
8 -> "B"
else -> "C"
}
}
fun getGrade2(score : Int) : String =
when (score) {
in 90...100 -> "A"
80...89 -> "B"
77 -> "Lucky"
else -> "C"
}
3. For
-
in
사용 - 범위
-
1..3
: 1 <= x <= 3 -
1 until 3
: 1 <= x < 3
-
for (i in 1..3) {
println(i)
}
for (i in 1..5 step 2) {
println(i)
}
for (i in 3 downTo 1) {
println(i)
}
for (i in 5 downTo 1 step 2) {
println(i)
}
val numbers = listOf(1, 2, 3)
for (number in numbers) {
println(number)
}
Exception
- 코틀린에서는 자바와 달리
Check Exception
과Unchecked Exception
을 구분하지 않는다try-catch
fun parseToInt(str : String) : Int {
try {
return str.toInt()
} catch (e : NumberFormatException) {
throw NumberFormatException("주어진 ${str}은 숫자가 아닙니다")
} finally {
println("finished method")
}
}
try-with-resource
- try-with-resource가 사라지고
use
사용
public void readFile(String path) throws IOExcepion {
try (BufferedReader reader = new BufferedReader(new FileReader(path))) {
System.out.println(reader.readLine());
}
}
↓↓↓↓↓
fun readFile(path : String) {
BufferedReader(FileReader(path)).use { reader ->
println(reader.readLine())
}
}
- Checked Exception
- Kotlin은 Checked Exception, Unchecked Exception 구분이 없고 모두 Unchecked Exception 이다
Function
- default parameter, named parameter 사용 가능
- 단, 자바 메서드에는 named parameter를 적용할 수 없다
fun repeat(str : String, num : Int = 3, newLine : Boolean = true) {
for (1..n) {
if (newline) {
println(str)
}
print(str)
}
}
repeat("hi", 2, true)
repeat("hi", 2)
repeat("hi")
repeat("hi", newLine=false)
-
Unit
: 자바의void
타입- 함수 정의에서 return 타입을 지정하지 않으면 코틀린은 Unit 함수를 정의한다고 가정
가변인자 (vararg)
-
vararg
사용
public static void printAll(String... strings) {
for (String string : strings) {
System.out.println(string);
}
}
↓↓↓↓↓
func printAll(vararg strings : String) {
for (str in strings) {
println(str)
}
}
확장함수
- 기존 클래스를 확장하여 새로운 함수를 추가해서 사용한다
- 마치 확장 함수를 기존 클래스 안에 존재하는 멤버 함수 처럼 사용 가능하다
- 확장함수에서는 클래스에 있는
private
,protected
멤버를 가져올 수 없다 (캡슐화가 깨지지 않게 하기 위해) -
멤버 함수와 확장 함수의 이름이 동일한 경우 멤버 함수가 호출된다
-
String
의 확장 함수 생성
fun main() {
val str = "ABC"
// 확장함수 사용
println(str.lastChar()) // C
}
fun String.lastChar() : Char {
return this[this.length - 1]
}
-
this
: 수신객체 -
String
: 수신객체 타입 - 확장 함수가 오버라이드 된 경우에는 해당 변수의 현재 타입의 확장 함수가 호출된다
val train : Train = Train()
train.isExpensive() // Train의 확장 함수
val train2 : Train = Ktx()
train.isExpensive() // Train의 확장 함수
val train3 : Ktx = Ktx()
ktx.isExpensive() // Ktx의 확장 함수
- 확장 프로퍼티
- 확장 함수처럼 프로퍼티로도 확장이 가능하다
val String.lastChar : Char
get() = this[this.length - 1]
중위 함수(infix)
- 코틀린에서 함수를 호출하는 새로운 방법
-
변수.함수이름(argument)
대신변수 함수이름 argument
로 호출 -
infix
키워드 사용
// 전통적인 함수
fun Int.add(other : int) {
return this + other
}
// infix 함수
infix fun Int.add2(other : int) {
return this + other
}
fun main() {
3.add(4) // 7
3.add2(4) // 7
3 add2 4 // 7
}
인라인 함수(inline)
- 함수가 호출되는 대신 함수가 호출되는 지점에 함수 내용이 그대로 삽입된다
- 함수를 파라미터로 전달할 때에 오버헤드를 줄일 수 있지만 성능저하를 유발할 수 있다
람다식
- 자바에서는 함수의 파라미터로 함수를 넘길 수 없었다
- Functional inferface를 사용해 함수로 넘기는 것 처럼만 사용 되었다
- 코틀린에서는 파라미터로 함수를 넣을 수 있다
- 람다식이 여러 줄일 경우 마지막 줄이 자동으로 return 값이 된다 (
return
키워드를 사용하지 않아도 됨)
fun main() {
val fruits = listOf(
Fruit("사과", 1_000),
Fruit("바나나", 2_000)
)
val isApple = { fruit : Fruit -> fruit.name == "사과"}
filterFruits(fruits, isApple)
}
private fun filterFruits(
fruits: List<Fruit>,
filter: (Fruit) -> Boolean
) : List<Fruit> {
return fruit.filter(filter) // List 내장함수
}
- 함수 파라미터로 함수를 넣을 때 축약도 가능하다
- return 타입이 추론 가능한경우 생략 가능
filterFruits(fruits, { fruit -> fruit.name == "사과"})
- 파라미터로 함수가 마지막 자리에 들어간다면 소괄호 밖으로 함수 파라미터를 뺄 수 있다
filterFruits(fruits) { fruit -> fruit.name == "사과"}
- 파라미터가 1개인 경우
it
으로 사용 가능하다filterFruits(fruits) { it.name == "사과"}
- return 타입이 추론 가능한경우 생략 가능