객체 없는 함수
저번 시간에 Hello Realm!
을 출력하기 위해 사용했던 코드를 다시 살펴봅시다.
fun main(args: Array<String>) {
println("Hello Realm!")
}
특이하게 클래스가 없습니다. 자바에서는 모든 함수가 클래스에 속해야 했는데 어떻게 코틀린에서 클래스가 없는 함수가 가능할 수 있을까요? 코를린은 자바 가상 머신에서 실행되는게 아닐까요? 이 의문을 풀기 위해서 실제 이 코드가 어떻게 동작되는지를 확인해봅시다. 커맨드라인에서 kotlin을 실행하기 위해 homebrew를 이용하여 kotlin을 설치합시다.
brew install kotlin
설치가 완료되면 kotlinc
를 이용해서 app.kt
파일을 컴파일해봅시다.
kotlinc app.kt
info: PERF: INIT: Compiler initialized in 459 ms
info: PERF: ANALYZE: 1 files (3 lines) in 488 ms
info: PERF: GENERATE: 1 files (3 lines) in 45 ms
컴파일이 끝났으면 javap
를 이용해서 컴파일된 AppKt
클래스를 살펴봅시다.
javap AppKt
Compiled from "app.kt"
public final class AppKt {
public static final void main(java.lang.String[]);
}
main
의 자세한 내용은 지금은 알 수 없지만 AppKt
클래스 안에 main
스태틱 메서드가 만들어진 것을 볼 수 있습니다. 코틀린에서 간단한 기능들은 메서드만으로 구성할 수 있고 이 메서드들은 파일명을 기준으로 자동으로 클래스가 생성되고 스태틱 메서드가 만들어진다는 것을 알 수 있습니다. 이 클래스들은 이름 뒤에 Kt
가 붙기 때문에 클래스 이름 뒤에 Kt
를 붙이지 않는 한 기존의 클래스와 충돌되지는 않습니다. main
안의 내용을 알기 위해서는 -c
옵션을 이용하면 볼 수 있습니다. 내부의 내용은 여기서 다룰 범위를 넘어가기 때문에 다루지 않겠습니다.
다양한 방법으로 함수 정의하기
간단한 함수를 정의해보겠습니다.
fun sum(a: Int, b: Int): Int {
return a + b
}
fun main(args: Array<String>) {
println("Hello Realm! ${sum(5, 3)}")
}
인텔리제이 환경에서는 이전과 같이 실행하면 됩니다. 만약 커맨드라인에서 수행하고 싶다면 아래와 같이 입력하세요.
kotlinc app.kt -include-runtime -d app.jar
info: PERF: INIT: Compiler initialized in 455 ms
info: PERF: ANALYZE: 1 files (8 lines) in 516 ms
info: PERF: GENERATE: 1 files (8 lines) in 50 ms
먼저 코틀린 런타임을 포함하여 결과물을 jar 파일로 뽑습니다. 그 후에 jar 파일을 수행하면 됩니다.
java -jar app.jar
Hello Realm! 8
반환값을 가진 함수는 반환값을 괄호뒤에 콜론(:)과 함께 붙입니다. sum
함수뒤에도 : Int
가 붙어있는 것을 볼 수 있습니다. 이 함수는 main
에서 호출되고 있습니다. 문자열 가운데 ${sum(5, 3)}
가 있는 것을 볼 수 있는데요. 이는 중괄호 안에 있는 내용 즉 sum(5,3)
을 수행한 결과를 문자열에 포함시키라는 것입니다. sum(5, 3)
이 수행된 결과 8
이 그 자리에 위치하게 되어 Hello Realm! 8
이 출력되게 합니다.
호출이 문자열 안에 있으니 번잡하네요. 상수를 이용해서 밖으로 빼겠습니다.
fun sum(a: Int, b: Int): Int {
return a + b
}
fun main(args: Array<String>) {
val a = sum(5, 3)
println("Hello Realm! ${a}")
}
val
은 상수를 선언하는 방식입니다. 값을 변경할 수 있는 변수가 필요한 경우에는 var
을 사용하면 됩니다. 타입은 자동으로 추론되기 때문에 적지 않았습니다.
굳이 적겠다면 아래와 같이 적을 수 있습니다.
fun sum(a: Int, b: Int): Int {
return a + b
}
fun main(args: Array<String>) {
val a: Int = sum(5, 3)
println("Hello Realm! ${a}")
}
타입을 상수명 뒤에 적어주었습니다.
변수나 상수를 문자열 가운데 출력하고 싶은 경우에는 중괄호를 생략할 수 있습니다.
fun sum(a: Int, b: Int): Int {
return a + b
}
fun main(args: Array<String>) {
val a = sum(5, 3)
println("Hello Realm! $a")
}
상수 이외에 변수를 사용할 수도 있습니다. val
대신에 var
를 사용해봅시다.
fun sum(a: Int, b: Int): Int {
return a + b
}
fun main(args: Array<String>) {
var a = sum(5, 3)
println("Hello Realm! $a")
}
sum
함수 자체를 조금 더 짧게 할 방법이 없을까요? 한줄 밖에 없는데 함수 블록을 쓰는 것은 좀 길어 보여요.
fun sum(a: Int, b: Int): Int = a + b
반환 값만 리턴하는 함수라면 return과 중괄호를 삭제하고 적을 수 있습니다.
반환 값도 추론을 통해 생략할 수 있습니다. 반환 값에 대한 타입 생략은 한줄 함수에서만 가능합니다.
fun sum(a: Int, b: Int) = a + b
아예 함수를 생략하는 방법은 없을까요? 람다를 사용할 수 있습니다.
fun main(args: Array<String>) {
val a = { a: Int, b: Int -> a + b }(3, 5)
println("Hello Realm! $a")
}
람다는 중괄호 구문 안에 인자를 적어주고 ->
을 적은 다음 반환 값을 뒤에 적어주면 됩니다.
함수에 조건식 사용하기
간단한 max를 함수로 만들어 봅시다.
fun max(a: Int, b: Int): Int {
if (a > b)
return a
else
return b
}
fun main(args: Array<String>) {
val value = max(3, 5)
println("Hello Realm! $value")
}
위의 두개의 리턴이 있지만 모두 하나의 if
에 속해있습니다. 이런 경우 코틀린에서는 조건식(conditional expressions)를 사용할 수 있습니다.
fun max(a: Int, b: Int) = if (a > b) a else b
fun main(args: Array<String>) {
val value = max(3, 5)
println("Hello Realm! $value")
}
조건문(conditional statements)를 사용할 경우 보다 조금 더 간결하게 코딩할 수 있습니다.
다음으로
다음 시리즈에서는 Null 처리, 타입, 캐스팅, 반복문, range 등을 다루겠습니다.
컨텐츠에 대하여
이 컨텐츠는 저자의 허가 하에 이곳에서 공유합니다.