Monday, November 13, 2017

Kotlin - Getting Started(Idioms)


오늘 순서는 kotlin 관용구이다.

Creating DTOs (POJOs/POCOs)


1
data class Customer(val name: String, val email: String)

kotlin의 데이터 클래스는 자동으로 getter와 (val을 읽기전용이라 val의 경우만 setter 지원) 기타 자바에서 재정의해서 써야했던 것들(equals, hashCode, toString, copy등)을 자동으로 지원해준다.(덕분에 자바와 달리 귀찮은 것들을 나열하듯 쓰지 않아도 된다.)

Default values for function parameters


1
fun foo(a: Int = 0, b: String = "") { ... }

파라미터의 기본값을 설정하려면 위와같이 선언과 동시에 값을 설정하면 된다.

Filtering a list

리스트에서 필터링하는 방법은 두가지가 있다.

1
val positives = list.filter { x -> x > 0 }

또는

1
val positives = list.filter { it > 0 }

이렇게 하면 0이상(양수)의 값만 필터링 되게 된다.

String Interpolation

String 안에서도 변수및 함수 사용이 가능한데 앞에 $를 붙혀주면 된다.

1
println("Name $name")

Instance Checks

자바의 switch~case 문과 유사하지만 여러 타입을 check 가능한 when의 사용법은 아래와 같다.

1
2
3
4
5
when (x) {
    is Foo -> ...
    is Bar -> ...
    else   -> ...
}

k , v 에 아무 이름이나 붙여도 된다.

Using ranges

범위 문법의 사용방법은 아래와 같다.

1
2
3
4
5
for (i in 1..100) { ... }  // 100을 포함한다.
for (i in 1 until 100) { ... } // 100을 포함하지 않는다.
for (x in 2..10 step 2) { ... }
for (x in 10 downTo 1) { ... }
if (x in 1..10) { ... }

Read-only list

리스트를 val로 선언하면 읽기 전용이 된다.

1
val list = listOf("a", "b", "c")

Read-only map

리스트와 마찬가지로 맵도 val로 선언해 읽기전용으로 만들 수 있다.

1
val map = mapOf("a" to 1, "b" to 2, "c" to 3)

Accessing a map

맵에 접근하는 방법은 아래와 같다.

1
2
println(map["key"])
map["key"] = value

Lazy property

지연 프로퍼티란 호출 시점에 초기화가 되는것을 말한다.

1
2
3
val p: String by lazy {
    // compute the string
}

지연로딩시 여러 이점이 있으나 그것은 나중에 설명 하도록 하겠다.

Extension Functions

코틀린에서는 이미 있는 클래스에 추가로 (확장) 함수 설정이 가능하다.

1
2
3
fun String.spaceToCamelCase() { ... }

"Convert this to camelcase".spaceToCamelCase()

Creating a singleton

코틀린에서는 싱글톤을 만들기 위해서는 object클래스만 붙혀주면 된다.(자바는.....)

1
2
3
object Resource {
    val name = "Name"
}

If not null shorthand


1
2
3
val files = File("Test").listFiles()

println(files?.size)

files가 null일경우 NPE가 발생하지 않고 null을 반환한다.
결과값: null

If not null and else shorthand


1
2
3
val files = File("Test").listFiles()

println(files?.size ?: "empty")

이 경우 files가 null이라면 기본값 "empty"가 출력된다.
결과값: empty

Executing a statement if null


1
2
val values = ...
val email = values["email"] ?: throw IllegalStateException("Email is missing!")

이 경우는 만일 values["email"]이 null 이면 IllgalStateExcption을 발생시킨다.
결과값: Exception in thread "main" java.lang.IllegalStateException: name is missing

Execute if not null


1
2
3
4
5
val value = ...

value?.let {
    ... // execute this block if not null
}

value가 null이 아니라면 let블럭이 실행된다.

Map nullable value if not null


1
2
3
val value = ...

val mapped = value?.let { transformValue(it) } ?: defaultValueIfValueIsNull

value가 null이 아니면 let블록이 실행되고, null 일 경우 defaultValueIfValueIsNull이 mapped의 값이된다.

Return on when statement


1
2
3
4
5
6
7
8
fun transform(color: String): Int {
    return when (color) {
        "Red" -> 0
        "Green" -> 1
        "Blue" -> 2
        else -> throw IllegalArgumentException("Invalid color param value")
    }
}

when은 return에 바로 사용이 가능하다.

'try/catch' expression


1
2
3
4
5
6
7
8
9
fun test() {
    val result = try {
        count()
    } catch (e: ArithmeticException) {
        throw IllegalStateException(e)
    }

    // Working with result
}

try-catch는 자바와 비슷한거 같다.

'if' expression


1
2
3
4
5
6
7
8
9
fun foo(param: Int) {
    val result = if (param == 1) {
        "one"
    } else if (param == 2) {
        "two"
    } else {
        "three"
    }
}

if문을 변수 선언 바로 사용 할 수 있다.

Builder-style usage of methods that return Unit


1
2
3
fun arrayOfMinusOnes(size: Int): IntArray {
    return IntArray(size).apply { fill(-1) }
}

Unit을 리턴해 Builder스타일을 사용할 수도 있다.

Single-expression functions


1
fun theAnswer() = 42

위의 식과 아래의 식은 동일하다.

1
2
3
fun theAnswer(): Int {
    return 42
}

이런식의 표현법을 when과 함께 유용하게 사용이 가능하다.

1
2
3
4
5
6
fun transform(color: String): Int = when (color) {
    "Red" -> 0
    "Green" -> 1
    "Blue" -> 2
    else -> throw IllegalArgumentException("Invalid color param value")
}

Calling multiple methods on an object instance ('with')


1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
class Turtle {
    fun penDown()
    fun penUp()
    fun turn(degrees: Double)
    fun forward(pixels: Double)
}

val myTurtle = Turtle()
with(myTurtle) { //100pix 사각형 그리기
    penDown()
    for(i in 1..4) {
        forward(100.0)
        turn(90.0)
    }
    penUp()
}

with를 이용해 연속적인 작업을 한번에 할 수 있다.

Java 7's try with resources


1
2
3
4
val stream = Files.newInputStream(Paths.get("/some/file.txt"))
stream.buffered().reader().use { reader ->
    println(reader.readText())
}

java7의 자원 자동 해제를 위와 같이 사용할 수 있다.

Convenient form for a generic function that requires the generic type information


1
2
3
4
5
6
//  public final class Gson {
//     ...
//     public <T> T fromJson(JsonElement json, Class<T> classOfT) throws JsonSyntaxException {
//     ...

inline fun <reified T: Any> Gson.fromJson(json: JsonElement): T = this.fromJson(json, T::class.java)

이부분은 잘 모르겠으나 대충 제너릭을 만드는 형식인거 같다.

Consuming a nullable Boolean


1
2
3
4
5
6
val b: Boolean? = ...
if (b == true) {
    ...
} else {
    // `b` is false or null
}

nullable한 Boolean값 사용하기.





정리하고 보니 자바보다 편리한 기능들이 많은것 같다.
알아 갈 수록 코틀린은 매력적인 언어임이 느껴진다.ㅎㅎ








0 개의 댓글:

Post a Comment