Android Development with Kotlin - Playing with Functions |
이 정리글은 Kotlin in Action 책을 보고 실무에 Kotlin 을 사용하던 사람이 몰랐던 내용이나 remind 하고 싶은 내용을 위주로 정리한 글입니다.
제대로 내용을 파악하시려면 책을 구매해서 읽어보세욤~
-
Function 과 Method 를 구분하는 논리..
Function 은 이름을 가진 Code 조각.
Method 는 class 와 연관되어진 function. member function 을 method 라 부른다.
논란의 여지는 있는데 Java 에는 Method 만 있다는 의견이 많다.
일각에서는 static function 은 function 이라고 이야기하기도 한다.
Kotlin 에서의 function 은 object 와 연관되어 있지 않은 function 을 이야기한다.
-
Argument 과 Parameter 를 구분하는 논리.
보통은 그 둘을 구분 없이 사용하지만 엄밀히 구분하자면...
아래의 코드에서 msg 는 parameter 이고, “testString” 이 argument 이다.
fun print(msg:String){ ... } print(“testString”)
-
val p = printSum(1, 2) println( p is Unit) // true
Unit 은 singleton 이다.
-
vararg 로 전달되는 녀석은 Array<T> 형태를 갖는다.
역시나 최적화를 위해 T 가 Int 인 경우 최적화된 형태인 IntArray 가 전달된다.
-
Tail-recursive functions 는 처음 본 개념이다.
아래 코드 형태를 tail-recursive function 이라 부른다.
꼬리쪽에서 recursive function call 을 하는 경우를 말한다.
fun getState(state:State, n:Int): State = if(n <=0) state else getState(nextState(state), n-1)
위와 같은 recursive function call 을 사용하는 경우에 n 이 높으면 StackOverflowError 가 날 수 있다.
이를 해결하는 방법은 recursive 를 푸는 것이다.
fun getState(state: State, n: Int) : State { var state = state for (i in 1..n){ state = state.nextState() } return state }
그러나 이렇게 푸는 방법은 조금 어려울 수 있다.
이를 Kotlin 에서 잘 도와준다.
“tailrec” modifier 를 써주면 알아서 StackOverflowError 가 나지 않게 최적화를 잘 해준다.
tailrec fun getState(state:State, n:Int): State = if(n <=0) state else getState(nextState(state), n-1)
tailrec 을 붙인 compile 된 코드를 decompile 하면 아래와 같은 코드를 얻는다
public static final State getState(@NotNull State state, int n){ while(true) { if(n <= 0) { return state; } state = state.nextState(); n = n - 1; } }
-
tailrec 를 붙일 수 있는 조건은 다음과 같다.
recursive call 이 last operation 으로 이루어져야 한다.
try/catch/finally block 이 아닌 곳에서 불러야 한다.
kotlin 에서만 사용 가능하다.
-
top-level function 으로 정의된 경우 전체에서 local function 부르듯이 호출할 수 있다.
단, top-level function 을 사용하려면 import 를 해야 한다.
물론 IDE 가 보통 자동으로 해준다.
// Test.kt package com.example fun printTwo() { print(2) } // Main.kt import com.example.printTwo fun main(args: Array<String>) { printTwo() }
가시성 때문에 top-level function 을 정의할 때는 주의해야 한다.
자동완성에 손쉽게 노출되어 나중에 주체할 수 없는 지경에 이를 수 있기 때문이다.
top-level function 이 compile 될 때 다음과 같은 형태를 띈다.
public final class TestKt{ public static void printTwo(){ print(2) } }
그래서 Java 에서 호출할 때 TestKt.printTwo() 와 같은 형태로 호출하는데..
Kt 가 붙은게 좋은 convention 은 아니기 때문에 @file:JvmName(“Printer”) 와 같은 annotation 을 넣어주면.
Java 에서 Printer.printTwo() 로 호출할 수 있다.
-
다른 파일에 정의한 top-level function 들이 하나의 class 로 compile 되길 원한다면 아래와 같이 하면 된다.
// Max.kt @file:JvmName(“Math”) @file:JvmMultifileClass package com.example.math fun max(n1: Int, n2:Int): Int = if(n1 > n2) n1 else n2 // Min.kt @file:JvmName(“Math”) @file:JvmMultifileClass package com.example.math fun min(n: Int, n2:Int): Int = if(n1 < n2) n1 else n2
-
Nothing type 은 empty type 이라고 부른다. 그 말은 instance 가 없다는 말이다.
Nothing 을 return 하는 함수는 return 을 하지 않는다는 말이다.
다시 말해 return statement 를 타지 않는다는 말이다.
이것은 무조건 exception 을 던지는 코드나 infinite loop 를 도는 코드들이 해당한다.
-
Nothing 은 모든 type 의 subtype 이기 떄문에 다음과 같은 코드가 가능하다.
fun fail(): Nothing = throw Error() val name:String = getName() ?: fail() // fail 은 Nothing 을 return
댓글