티스토리 뷰

kotlin

kotlin 1.4

LichKing 2020. 10. 1. 17:32

얼마전 코틀린 1.4 버전이 릴리즈됐다. 추가된 기능들에 대해 간략히 살펴보자.

 

# SAM conversions for Kotlin interfaces

지금까지 코틀린은 SAM(Single Abstract Method, 추상메서드가 하나뿐인 인터페이스) 에 대해 람다 표현식을 지원하지않았다. 함수 자체를 타입으로 나타낼 수 있었기때문에 함수 타입에만 람다를 지원하고, 자바의 함수형 인터페이스(마찬가지로 추상메서드가 1개인 인터페이스)만 람다로 표현할 수 있었다.

fun main() {
    val calculator = object: Calculator {
        override fun add(n1: Int, n2: Int): Int = n1 + n2
    }
}

interface Calculator {
    fun add(n1: Int, n2: Int): Int
}

코틀린에서 SAM 에 대해 즉시 구현하려면 위와 같은 코드를 작성했어야 했다. 이걸 람다로 표현할 수 있게 변경됐다.

fun main() {
    val calculator = Calculator { n1, n2 -> n1 + n2 }
}

fun interface Calculator {
    fun add(n1: Int, n2: Int): Int
}

다만 람다로 표현하려면 interface 앞에 fun 키워드를 붙여줘야한다.

 

# Mixing named and positional arguments

개인적으로 매우 반가운 기능이다. 코틀린은 함수에 파라미터를 전달할때 파라미터명을 활용할 수 있는데, 이름을 명시한 다음 파라미터는 순서가 일치하더라도 무조건 이름을 넣어줬어야했다.

fun main() {
    val inter = object: Calculator {
        override fun add(n1: Int, n2: Int): Int = n1 + n2
    }

    inter.add(n1 = 5, 1)
}

기존에는 이런 코드가 컴파일되지 않았다는 얘기다. n1 에 이름을 명시했기때문에 n2에도 반드시 해줘야한다. 반대의 경우에는 정상적으로 컴파일된다. 코틀린 1.4 부터는 순서만 맞는다면 위 코드도 컴파일이 되게된다.

 

# Trailing comma

이것도 은근히 편리한 기능이 될것같은데 메서드 호출이나 프로퍼티 나열 등 쉼표(,)가 들어가는 케이스에 대해 당연하게도 가장 마지막은 쉼표를 넣으면 안됐었다. 하지만 쉼표로 코드가 끝나도 정상적으로 컴파일이 되도록 변경됐다.

class Person(
    val age: Int,
    val name: String,
)

이런 코드도 정상적으로 컴파일된다.

 

# Callable reference improvements

## References to functions with default argument values

메서드 레퍼런스에 관련된 내용인데.. 코틀린을 사용하면서는 메서드 레퍼런스를 사용할 일이 거의 없어 잘 쓸지는 모르겠다. 굳이 메서드 레퍼런스를 쓰지않아도 코드양에서 별 차이없는 코드가 만들어지다보니 손이 잘 안가게 되는듯..

fun main() {
    outer(::inner)
}

fun outer(inner: () -> String) {}
fun inner(n: Int = 10): String = "hello kotlin"

outer() 함수에 inner() 함수를 전달하려고 한다. outer() 함수 파라미터의 타입을 보면 인자는 없고 String 을 반환한다. inner() 함수의 시그니처를 보면 n 파라미터를 받지만 기본값이 들어가있으니 파라미터 없이도 호출할 수 있음을 알 수 있다. 하지만 위 코드는 1.3 에선 컴파일되지 않았다. 1.4 에서는 이부분이 개선되었다.

 

## Function references in Unit-returning functions

fun main() {
    outer(::inner)
}

fun outer(inner: () -> Unit) {}
fun inner(): String = "hello kotlin"

이번엔 outer() 함수가 Unit 을 리턴하는 함수를 파라미터로 받고있다. inner() 함수는 String 을 리턴하고 있으므로 outer() 에 전달될 수 없다. 하지만 잘 생각해보면 Unit 을 리턴하는건 void 와 마찬가지이므로 리턴 타입을 추적하고, 활용해야하는 경우가 아니라면 굳이 뭘 리턴하든 상관없다. 1.4 부터는 위 코드도 컴파일되게 된다.

 

## References that adapt based on the number of arguments in a function

fun main() {
    outer(::inner)
}

fun outer(inner: (Int) -> Int) {}
fun inner(vararg n: Int): Int = n.size

메서드를 전달 할 때 가변 파라미터를 받는 메서드도 타입이 일치한다면 전달 할 수 있다.

 

## Suspend conversion on callable references

fun main() {
    outer(::inner)
}

fun outer(inner: suspend (Int) -> Int) {}
fun inner(n: Int): Int = n

suspend 가 붙은 경우에도 기존에는 컴파일되지 않았지만 1.4 부터 개선됐다.

 

# New more powerful type inference algorithm

1.4 부터 더 강력한 타입 추론 알고리즘이 적용됐다. 1.3 에서는 옵션을 통해 활성화 할 수 있었지만, 1.4 부터는 디폴트로 적용됐다.

 

## SAM conversion for java interfaces with different arguments

코틀린에서 자바 코드를 호출할 때, 자바 메서드의 파라미터가 함수형 인터페이스를 2개 이상 받는 경우 하나는 객체형, 하나는 람다로 전달하는게 지원되지 않았다. 객체형으로 할거면 모두 객체형으로 하고, 람다로 할거면 모두 람다로 했어야하는데 이런 불편함이 개선됐다.

public class A {
    public static void test(Runnable r1, Runnable r2) {

    }
}

fun main() {
    A.test(object: Runnable {
        override fun run() {
            TODO("Not yet implemented")
        }
    }) { }
}

 

# New modes for generating default methods

코틀린 인터페이스에 구현 메서드를 작성할 경우 이를 자바 인터페이스의 디폴트 메서드로 컴파일하기위해선 @JvmDefault 애노테이션과 -Xjvm-default 옵션을 활성화시켰어야했다. 코틀린 1.4 부터는 -Xjvm-default=all 설정을 활성화시킬경우 모든 구현메서드를 디폴트 메서드로 컴파일한다.

 

# Unified exception type for null checks

코틀린에서는 null 예외를 발생시킬때 상황에 따라 각기 다른 예외를 발생시켰다.(KotlinNullPointerException, IllegalStateException.. 등등) 이를 java.lang.NullPointerException 으로 통일시켰다.

댓글
댓글쓰기 폼