Google for Mobile I/O RECAP 2018 (07)

07. Developer. Kotlin으로 코딩 시작하기

  • 발표자 : Hadi Hariri (VP of Developer Advocacy, Jetbrains)
  • 세션설명 : 한 번도 사용해보지 않은 개발자는 있어도, 한 번만 사용해 본 개발자는 없다! 사용해본 개발자의 95%가 높은 만족도를 보였다는 Kotlin! 작년 안드로이드 공식 언어로 채택된 이후 매년 빠르게 성장하고 있는 Kotlin을 시작해보세요. Google I/O에서 Kotlin을 발표했던 Jetbrain의 Hadi Hariri가 한국 개발자를 위해 직접 소개합니다.

코틀린 지식이 없는 상태에서 단편적인 키워드들로 정리한 세션이라 샘플코드 등 임의로 넣은 부분이 많습니다.

Kotlin 시작시 Android Studio의 Java to Kotlin 메뉴에 의존하지 말 것.

Property & Field

Kotlin은 필드는 없고 프로퍼티만 사용함.

참고 : https://kotlinlang.org/docs/reference/properties.html#backing-fields

Fields cannot be declared directly in Kotlin classes.

  • field: A data member of a class. Unless specified otherwise, a field is not static. - 클래스의 데이터 멤버. 특별히 언급되지 않았다면 field는 정적이지 않다.
  • property: Characteristics of an object that users can set, such as the color of a window - 윈도우의 색과 같이, 사용자가 설정할 수 있는 객체의 특성

Delegated Properties

참고 : https://kotlinlang.org/docs/reference/delegated-properties.html

  • lazy properties : 첫 번째 액세스시에만 값이 계산되어 저장됨.

    val lazyValue: String by lazy {
        println("computed!")
        "Hello"
    }
    
    fun main(args: Array<String>) {
        println(lazyValue)
        println(lazyValue)
    }
    This example prints:
    
    computed!
    Hello
    Hello
  • observable properties : 리스너는 속성 변경에 대해 알림을 받음.

    import kotlin.properties.Delegates
    
    class User {
        var name: String by Delegates.observable("<no name>") {
            prop, old, new ->
            println("$old -> $new")
        }
    }
    
    fun main(args: Array<String>) {
        val user = User()
        user.name = "first"
        user.name = "second"
    }
    This example prints:
    
    <no name> -> first
    first -> second
  • 맵에 여러 필드를 대신해 프로퍼티를 저장함.

    class User(val map: Map<String, Any?>) {
        val name: String by map
        val age: Int     by map
    }
    ...
    val user = User(mapOf(
        "name" to "John Doe",
        "age"  to 25
    ))
    ...
    println(user.name) // Prints "John Doe"
    println(user.age)  // Prints 25

Standard Library (Built-in)

lazy, vetoable 등 제공함.

funtion expression

참고 : https://kotlinlang.org/docs/reference/basic-syntax.html#defining-functions

// basic
fun sum(a: Int, b: Int): Int {
    return a + b
}

// expression
fun sum(a: Int, b: Int) = a + b

when expression

참고 : https://kotlinlang.org/docs/reference/basic-syntax.html#using-when-expression

https://kotlinlang.org/docs/reference/control-flow.html#when-expression

fun describe(obj: Any): String =
when (obj) {
    1          -> "One"
    "Hello"    -> "Greeting"
    is Long    -> "Long"
    !is String -> "Not a string"
    else       -> "Unknown"
}

exception expression

참고 : https://kotlinlang.org/docs/reference/exceptions.html

// basic
try {
    // some code
}
catch (e: SomeException) {
    // handler
}
finally {
    // optional finally block
}

// expression
val a: Int? = try { parseInt(input) } catch (e: NumberFormatException) { null }

Elvis operator

참고 : https://kotlinlang.org/docs/reference/null-safety.html

// basic
val l: Int = if (b != null) b.length else -1

// Elvis operator
val l = b?.length ?: -1

// Elvis operator (Exception)
val name = node.getName() ?: throw IllegalArgumentException("name expected")

Collections

sortWith

참고 : https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/sort-with.html?q=sortwithc&p=0

data class Product(val name: String, val price: Double /*USD*/)
...
fun main(args : Array<String>){
	val products = arrayOf(Product("iPhone 8 Plus 64G", 850.00),
							Product("iPhone 8 Plus 256G", 1100.00),
							Product("Apple iPod touch 16GB", 246.00),
							Product("Apple iPod Nano 16GB", 234.75),
							Product("iPad Pro 9.7-inch 32 GB", 474.98),
							Product("iPad Pro 9.7-inch 128G", 574.99),
							Product("Apple 42mm Smart Watch", 284.93))
		
	products.sortWith(object: Comparator<Product>{
								override fun compare(p1: Product, p2: Product): Int = when {
													p1.price > p2.price -> 1
													p1.price == p2.price -> 0
													else -> -1
												}
					  })
}

map

참고 : https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/map.html

var strCustList = customerList.map { it -> if(it!=null) "${it.name} lives at street ${it.address.street}" else null }
strCustList.forEach{println(it)}

mapNotNull

참고 : https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/map-not-null.html

publicp  inline fun <T, R : Any> Iterable<T>.mapNotNull(transform: (T) -> R?): List<R>

Null declare (?) 하지 말 것.

참고 : https://kotlinlang.org/docs/reference/basic-syntax.html#using-nullable-values-and-checking-for-null

Java를 위해서 만들어진 것.

In Kotlin, the type system distinguishes between references that can hold null (nullable references) and those that can not (non-null references). For example, a regular variable of type String can not hold null:

https://kotlinlang.org/docs/reference/null-safety.html

To perform a certain operation only for non-null values, you can use the safe call operator together with let:

If you have a collection of elements of a nullable type and want to filter non-null elements, you can do so by using filterNotNull:

Semicolons

참고 : http://kotlinlang.org/docs/reference/grammar.html#semicolons

Kotlin provides "semicolon inference": syntactically, subsentences (e.g., statements, declarations etc) are separated by the pseudo-token SEMI, which stands for "semicolon or newline". In most cases, there's no need for semicolons in Kotlin code.

Inline Functions

참고 : https://kotlinlang.org/docs/reference/inline-functions.html

https://blog.uzuki.live/advanced-kotlin-inline-functions-1-basic/

https://blog.uzuki.live/inline-functions-2-local-return/

고차 함수(higher-order functions) 사용시 특정 런타임에서 패널티가 부과되며, 메모리 할당과 가상 호출은 런타임 오버헤드를 초래한다고 함.

이런 종류의 오버헤드는 람다 식을 inlining 함으로써 제거될 수 있음.

람다 사용시에만 inline 사용이 가능하며 퍼포먼스 개선이 가능하다.

Local Return 문에도 사용됨.

Functional Programming

return 타입을 명시해야 함.

fun Division(a: Int, b: Int): Int {
    return DivisionVaild(result)
    //return DivisionInvaild(result)
}

fun DivisionVaild(val result: Int)
fun DivisionInvaild(val result: String)

Sealed Classes

참고 : https://kotlinlang.org/docs/reference/sealed-classes.html

Sealed Class와 서브클래스는 같은 파일에 선언되어야 함.

Sealed Class는 abstract Class임. 직접 인스턴스화 할수 없고 abstract 멤버는 가질수 있음.

non-private constructors를 가지면 안됨.

주로 when 표현식에서 유용함.

sealed class Expr {
    data class Const(val number: Double) : Expr()
    data class Sum(val e1: Expr, val e2: Expr) : Expr()
	object NotANumber : Expr()
}
fun eval(expr: Expr): Double = when(expr) {
    is Const -> expr.number
    is Sum -> eval(expr.e1) + eval(expr.e2)
    NotANumber -> Double.NaN
    // the `else` clause is not required because we've covered all the cases
}

Q&A

시간 관계상 생략

+ Recent posts