본문 바로가기
프로그래밍 놀이터/Kotlin, Coroutine

[Kotlin Tutorial] 함수 정의하고 호출하기 #2

by 돼지왕 왕돼지 2017. 8. 3.
반응형

 [Kotlin Tutorial] 함수 정의하고 호출하기 #2


참조 : Kotlin in Action


3.4. Working with collections: Varargs, Infix calls, and Library support


3.4.1. Extending the Java collections API


-

val strings: List<String> = listOf(“first”, “second”, “thrid”)

strings.last()


val numbers: Collection<Int> = setOf(1, 14, 2)

numbers.max()


last 와 max 는 extension 이다.

이 외에도 많이 있으니 IDE 의 code completion 을 잘 활용해보시라~




3.4.2. Varargs: functions that accept an arbitrary number of arguments


-

fun listOf<T>(vararg values: T): List<T>{ … }


Java 에서 … 으로 쓰던 녀석 대신 확실하게 vararg 라는 키워드를 써준다

형태는 array 가 된다



-

Spread operator 라는 게 있다

fun main(args: Array<String>){

    val list = listOf(“args: “, *args) // args unpack 된다, array 를 concat 할 때 좋다

}




3.4.3. Working with pairs: infix calls and destructuring declarations


-

infix call 이란 method name 다음에 바로 parameter 를 쓰는 방식을 말한다.

to(“one”) // regular call

to “one” // infix call



-

infix call 은 1개의 param 을 받는 함수면 일반 function 던 extension function 이던 다 사용할 수 있다.

function 이 infix notation 으로 쓸 수 있도록 하려면 infix modifier 를 추가해야 한다.

infix fun Any.to(other: Any) = Pair(this, other)

( Any 에 대해서는 나중에 배운답니당, Object 같은 녀석이에요 )



-

Pair 를 이용해서 2개의 var 를 한번에 init 할 수도 있다.

val (number, name) = 1 to “one”


요런 녀석을 destructuring declaration 이라고 한다.

이 destructuring declaration 은 map 의 iteration 등에도 사용된다.

for ( (index, element) in collection.withIndex() ){

    println(“$index: $element”)

}



-

to 는 extension function 이다.

그런데 이 녀석은 generic receiver 라서 어떤 type 이든 다 받아줄 수 있다.


1 to “one”, “one” to 1, list to list.size() 등 다 된다




3.5. Working with strings and regular expressions


3.5.1. Splitting strings


-

Java 의 split method 는 정말 많이 사용된다.

그러나 param 으로 regular expression 을 받기 때문에 사람들이 가장 많이 하는 실수가 “.” 으로 split 하는 것이다.

"12.345-6.A”.split(“.”) // 결과는 empty array, . 은 regex 로 any char


이런 혼란을 막기 위해 String 에 toRegex() extension 이 추가되었고, 이 녀석의 type 은 Regex 이다.

split 은 String 과 RegEx 두가지 type 을 다루는 녀석들로 각각 구현되었다.

"12.345-6.A".split('.")

"12.345-6.A".split("\\.|-".toRegEx()))


여러 개의 delimiter 를 사용할 수 있는 녀석(varargs 형태)도 정의되었다. ( Auto complete 을 잘 이용해보세영~ )




3.5.2. Regular expressions and triple-quoted strings


-

substringBeforeLast("/"), substringAfterLast("/") 등의 extension 도 생겼다.

url 을 parsing 할 때 좋다.



-

fun parsePath(path: String){

    val regex = “””(.+)/(.+)\.(.+)”””.toRegex() //  toRegex 를 할 때 오히려 일반 . 을 escape 해야 한다

    val matchResult = regex.matchEntire(path)

    if(matchResult != null){

        val (directory, filename, extension) = matchResult.destructured

        println(“Dir: $directory, name: $filename, ext: $extension”)

    }

}


“””regExp””” 를 사용하면 escape 가 필요없다.

\\. 대신 \. 을 쓰면 된다. ( 실제 . 표현할 경우 )


desturctured 함수를 통해 destructuring declaration 도 가능하다




3.5.3. Multiline triple-quoted strings


-

“”” 는 escape character 방지는 물론 line break 가 있는 text 를 쉽게 쓸 수 있게 한다.

\n 같은 것도 필요 없고, \ 도 escape 할 필요도 없다

val kotlinLogo = “””|  //

                              .|//

                              .|/  \”””

println(kotlinLogo.trimMargin(“.”)) // . 을 기준으로(포함해서) preceding margin 을 제거한다



-

“”” 안에는 string template 도 쓸 수 있다.

그럼 $ 는 어떻게 표시할 것인가?

val price = “””${‘$’}99.9””” // 이 녀석은 불행히도 이렇게 써야 한다


val a = 3

println("""$a""") // 3

println("""$$a""") // $3

println("""${'$'}a""") // $a



-

이 multiline triple-quoted string 은 test 할 때 big string 을 그냥 복붙해서 사용할 때 좋다.

그리고 trimMargin 과 조합해서 사용하면 더 좋다



-

extension function 은 이렇게 강력하다.

대부분의 Kotlin lib 은 Java lib 에 extension 을 한 것이고,

Anko 라는 녀석은 android lib 을 extension 한 것이다.

그 외에도 Spring 같은 녀석들도 extension 을 사용했고, 다른 3rd party extension 도 많다.




3.6. Making your code tidy: local functions and extensions


-

Function extraction 을 하다보면 코드를 이해하는 데 어려울 수 있고,

inner class 를 만들어 그곳에 해당 function 들을 넣다보면 구조에 대한 유지보수가 또 들어간다.

이 때 쓰는 것은 local function 이다.

class User(val id: Int, val name: String, val address: String)


fun saveUser(user: User){

    if( user.name.isEmpty()) ){

        throw IllegalArgumentException(“Can’t save user ${user.id}: empty Name”)

    }


    if( user.address.isEmpty()){

        throw IllegalArgumentException(“Can’t save user $user.id}: empty Address”)

    }


    // save user to DB

}



class User(val id: Int, val name: String, val address: String)


fun saveUser(user: User){

    fun validate(value: String, fieldName: String){

        if( value.isEmpty() ){

            throw IllegalArgumentException(“Can’t save user ${user.id}: empty $fieldName”)

        }

    }


    validate(user.name, “Name”)

    validate(user.address, “Address”)

}


local function 은 enclosing function 의 모든 variable 과 parameter 를 사용할 수 있다.



-

local function 을 사용할 때는 deep nested 가 되지 않도록 해야 한다는 것.




3.7. Summary

-

Kotlin 은 자신만의 collection 을 정의하지 않고 Java 의 것을 사용하면서 extension 으로 API 를 더 강화했다.



-

Default value 를 잘 사용하면 overload function 을 많이 줄일 수 있다.

그리고 named-argument 는 훨씬 가독성 좋게 코드를 짤 수 있게 해준다.



-

function 과 property 는 file 에 바로 쓰일 수 있다. ( class 안이 아닌 top level )

이 녀석들은 static function, static variable 로 작동한다.



-

extension function 은 소스코드 유무 상관없이 존재하는 모든 class 를 확장할 수 있게 해준다.

물론 runtime overhead 는 없다.



-

infix call 은 single arg 일 경우 쓸 수 있는데 operation 같은 형태로 더 깔끔하게 코드를 쓸 수 있게 해준다.



-

Kotlin 은 string 을 다루는 여러 편리한 함수들을 제공한다.

그리고 이는 일반 string 과 regex string 모두 지원한다



-

triple-quoted string 은 읽기 어려운 escaping 관련된 코드와 string concatenation 을 방지해준다.



-

Local function 은 code 의 구조를 더 깔끔하게 가져가면서 중복코드를 줄이는 데 기여할 수 있다.





반응형

댓글