2017년 5월 18일 구글I/O 행사에서 안드로이드 공식 언어로 코틀린(Kotlin)이 추가가 되었다. 이에 따라 Kotlin의 관심도가 급증했다. 여러 가지 이유가 있겠지만, IOS에서 Objective-C에서 Swift로 간결한 문법 체계를 택한 것처럼 Android도 간결한 문법 체계로 변경하려는 것 같다.
Kotlin을 대체 왜 해야 하는가? 무엇인가? 에 대한 글은 안드로이드 공식 언어가 된 Kotlin을 알아보자 여기에 잘 써져있으니 한 번 읽어보자.
앞으로 코틀린이 많이 쓰일 것 같으니 간단히 코틀린 문법에 대해 알아보고자 한다.
1. 문법 특성
- python과 동일하게 ; 를 생략 가능하다.
- package 정의는 java와 동일하다.
- Javascript 처럼 변수 선언 시 명시적으로 타입을 지정해주지 않아도 된다.
- 기본 연산은 java와 동일하다.
- 문자열(String)을 마치 정규표현식처럼 다룬다.
여러 가지 특성이 있지만, 단순하게 보면 위와 같다.
2. 변수
변수 선언은 내가 익혀본 언어들 중 가장 특이한? 형태인 것 같다. 굳이 비슷한 언어를 꼽자면 Javascript라고 말할 수 있겠다.
val 변수명: 타입 = 값
val a: Int = 1
var b = 2 // Int형으로 할당, var로 해도 됨
val c: Double
c = 3.0
변수를 선언과 동시에 초기화할 경우에는 변수명 뒤에 타입을 써주지 않아도 되지만, 초기화를 나중에 할 경우에는 꼭 타입을 명시해주어야 한다.
3. 문자열
String templates을 사용해서 문자열을 손쉽게 다룰 수 있다. 하지만 아쉽게도 java의 문자열 간 +
연산을 지원하지 않는다.
x// 다른 변수 값과 문자열 결합
val count = 11
val str1 = "count is $count" // count is 11
// 문자열 치환
val str2 = "${str1.replace("count", "개수")}, but not end" // 개수 is 11, but not end
// 여러 줄의 문자열 담기
val strs1 = """
문자열1
문자열2
문자열3
""".trimIndent()
/* 결과
문자열1
문자열2
문자열3 */
val strs2 = """
문자열1
문자열2
문자열3
"""
/* 결과
문자열1
문자열2
문자열3 */
더 많은 string templates 예시는 여기 에서 볼 수 있다.
또한, Java에서는 String의 문자에 접근하기 위해 charAt 함수를 사용해야 했지만, 인덱싱으로 간단히 접근할 수 있다.
xxxxxxxxxx
// 문자열 내 문자 접근
val str = "Hello kotlin world"
var item: Char
item = str[0] // H
item = str[3] // l
// 정수를 문자열로 변환
val num = 3423
num.toString()
4. 함수
함수 형태는 변수의 형태 변화를 고려하면 이해가 되는 형태다.
fun 함수명(param1: 타입, param2: 타입): 반환타입 { 내용 }
xxxxxxxxxx
fun sum(a: Int, b: Int): Int {
return a + b
}
// 위와 동일한 함수이지만, 이렇게도 정의할 수 있다.
fun sum(a: Int, b: Int) = a + b
반환이 없는 함수 (void -> Unit)
xxxxxxxxxx
fun printSum(a: Int, b: Int): Unit {
println("sum of $a and $b is ${a+b}")
}
// 반환 타입을 생략가능
fun printSum(a: Int, b: Int) {
println("sum of $a and $b is ${a+b}")
}
fun printSum(a: Int, b: Int) = println("sum of $a and $b is ${a+b}")
null 값 반환할 수 있도록 하기
반환타입 뒤에 ?
을 붙여 Int, Double, Float과 같이 반환타입이 기본 자료형이어도 null 값을 반환하도록 할 수 있다.
xxxxxxxxxx
fun parseInt(str: String): Int? {
.. ..
// 반환할 수 없으면
return null
}
fun printProduct(arg1: String, arg2: String) {
val x = parseInt(arg1)
val y = parseInt(arg2)
// Using `x * y` yields error because they may hold nulls.
if (x != null && y != null) {
// x and y are automatically cast to non-nullable after null check
println(x * y)
}
else {
println("either '$arg1' or '$arg2' is not a number")
}
}
임의 타입 받기(Any)
xxxxxxxxxx
fun getStringLength(obj: Any): Int? {
if(obj is String) {
// 타입 확인하는 is문을 거치면 자동으로 형변환된다.
return obj.length
}
return null
}
// or
fun getStringLength(obj: Any): Int? {
if(obj !is String) return null
// 이 경우에도 역시 자동적으로 String으로 형변환된다.
return obj.length
}
5. 배열(리스트), 반복문
기존의 Java 배열처럼 생성할 수 없고 listOf 함수를 통해 배열(리스트)를 생성해야 한다. 또한, 기존의 for문 구문은 사용할 수 없고 foreach문처럼 사용해야 한다.
xxxxxxxxxx
val items = listOf(3, 1, 4, 2, 5, 5)
for(item in items) {
println(item)
}
val items1 = listOf("apple", "banana", "tomato")
for(index in items1.indices) {
println("item at $index is ${items[index]}") // 복수의 변수면 ${}로 묶어줌
}
하지만 ranges를 이용해서 기존의 for문과 비슷하게 사용할 수도 있긴 하다.
xxxxxxxxxx
for(x in 1..5) { // 12345
print(x)
}
for(x in 1..10 step 2) { // 13579
print(x)
}
for(x in 9 downTo 0 step 3) { // 9630
print(x)
}
val list = listOf(1, 2, 3, 4, 5, 7, 9)
for(i in 0..list.size step 2) {
print(list[i]) // 1 3 5 7
}
while문 사용하는 방법은 동일하다.
xxxxxxxxxx
val items = listOf("kiwi", "banana", "peanut")
val index = 0
while(index < items.size) {
println("item at $index is ${items[index]}")
index++
}
추가적으로 리스트 내 다양한 내장 람다함수를 통해 리스트를 수월하게 다룰 수 있다.
xxxxxxxxxx
val fruits = listOf("banana", "avocado", "apple", "kiwifruit")
fruits
.filter { it.startsWith("a") }
.sortedBy { it }
.map { it.toUpperCase() }
.forEach { println(it) }
6. if문
if문의 사용법은 java와 동일하다. 그러나 ranges를 활용해서 다양한 것들을 할 수 있게 됐다.
xxxxxxxxxx
val list = listOf("a", "b", "c", "d")
// list 내에 "a" 문자열이 있는지 확인
if("a" in 0..list.lastIndex)
println("a is in list")
else
println("a is not in list")
if("d" !in 0..list.lastIndex)
println("d is not in list")
7. when 표현식
when
은 C의 switch-case 구문과 같다고 보면 된다.
xxxxxxxxxx
when(x) {
1 -> print("x==1")
2 -> print("x==2")
else -> {
print("x is neither 1 nor 2")
}
}
하지만 switch-case문보다 활용도가 더 높다. case 부분에 구문이나 함수를 사용할 수 있다.
when(x) {
0, 1 -> print("x == 0 or x == 1")
else -> print("otherwise")
}
val s = "12"
when(x) {
parseInt(s) -> print("s encodes x")
else -> print("s does not encode x")
}
when(x) {
in 1..10 -> print("x is in the range")
in validNumbers -> print("x is vaild")
!in 10..20 -> print("x is outside the range")
else -> print("none of the above")
}
when {
"orange" in items -> println("juicy")
"apple" in items -> println("apple is fine too")
}
// when 구문을 함수로 정의
fun whatType(x: Any) = when(x) {
is String -> print("string length is ${x.length}")
is Int -> print("Int")
else -> print("Double or Float or Boolean")
}
추가적으로, val 키워드를 이용한 변수 선언은 재할당을 할 수 없으며, 일반 변수로 사용하려면 var를 사용해야 한다.
'Android' 카테고리의 다른 글
[Kotlin] 코틀린에서 형변환은 어떻게 할까 (0) | 2018.10.17 |
---|---|
[Java][Kotlin] 액티비티 전환하기 (3) | 2018.10.13 |
[Java][Kotlin] Fragment 간단 사용법 (3) | 2018.10.13 |
댓글