Contents
슬럼프가 길어져 약 1년 정도를 블로그도 쉬고 개발도 쉬었던 것 같다. 전에 공부했던 내용은 다 잊어버렸기 때문에 다시 리프레쉬하는 마음으로 Kotlin을 처음부터 새로 공부하려고 한다.
Kotlin Basic Syntax (1)
Kotlin 코틀린은 더 적은 코드와 가독성이 결합된 언어라고 한다. 그래서 보다 다른 개발자의 코드를 이해하기가 쉽다고 한다. google 내부 데이터에 따르면 Kotlin으로 구축된 앱은 충돌 가능성이 20% 적다는 결과가 있다. 또, 다중 플랫폼 개발을 지원한다는 장점도 있는 등 많은 이점이 있는 Kotlin 언어를 배워보려고 한다.
Program entry point - 프로그램 진입점
Kotlin에서의 program entry point인 main 함수는 아래와 같이 2가지 버전으로 사용할 수 있다.
//인자를 받지 않는 main 함수
fun main() {
println("Hello world!")
}
//여러개의 String 인자를 받는 main 함수
fun main(args: Array<String>) {
println(args.contentToString())
}
Functions - 함수
Kotlin에서의 파라미터 선언은 변수명: 타입과 같고, 리턴 타입은 마지막에 선언해준다.
fun sum(a: Int, b: Int): Int {
return a + b
}
fun main() {
print("sum of 3 and 5 is ") //sum of 3 and 5 is 8
println(sum(3, 5))
}
함수 본문은 표현식이 될 수 있고, 리턴 타입은 유추된다.
fun sum(a: Int, b: Int) = a + b
fun main() {
println("sum of 19 and 23 is ${sum(19, 23)}") //sum of 19 and 23 is 42
}
리턴 값이 없으면 void 대신 Unit을 사용하고, Unit 타입은 생략 가능하다.
fun printSum(a: Int, b: Int): Unit {
println("sum of $a and $b is ${a + b}")
}
fun main() {
printSum(-1, 8) //sum of -1 and 8 is 7
}
//--------------------------------------------
//Unit type 생략
fun printSum(a: Int, b: Int) {
println("sum of $a and $b is ${a + b}")
}
Variables - 변수
읽기 전용 local 변수는 val 키워드를 사용하고, 값은 한 번만 할당될 수 있다. 유형 추론, 지연 할당도 가능하다.
fun main() {
val a: Int = 1
val b = 2
val c: Int
c = 3
println("a = $a, b = $b, c = $c") a = 1, b = 2, c = 3
}
값을 여러 번 할당할 수 있는, 즉 재할당이 가능한 local 변수는 var 키워드를 사용한다.
fun main() {
var x = 5
x += 1
println("x = $x") //x = 6
}
Class / Instances - 클래스 및 인스턴스
Class 선언에 파라미터들을 정의할 수 있고, 자동으로 생성자를 사용할 수 있다.
class Rectangle(val height: Double, val length: Double) {
val perimeter = (height + length) * 2
}
fun main() {
val rectangle = Rectangle(5.0, 2.0)
println("The perimeter is ${rectangle.perimeter}") //The perimeter is 14.0
}
Class를 상속 가능하도록 하려면 open 키워드를 사용해서 선언해야 하고, 상속은 :(콜론)을 사용한다.
open class Shape
class Rectangle(val height: Double, val length: Double): Shape() {
val perimeter = (height + length) * 2
}
Conditional Expressions - 조건식
fun maxOf(a: Int, b: Int): Int {
if (a > b) {
return a
} else {
return b
}
}
fun main() {
println("max of 0 and 42 is ${maxOf(0, 42)}") //max of 0 and 42 is 42
}
if문은 아래와 같이 표현식으로 사용할 수 있다.
fun maxOf(a: Int, b: Int) = if (a > b) a else b
for loop - for문
val items = listOf("apple", "banana", "kiwifruit")
for (item in items) {
println(item)
}
val items = listOf("apple", "banana", "kiwifruit")
for (index in items.indices) {
println("item at $index is ${items[index]}")
}
/*item at 0 is apple
item at 1 is banana
item at 2 is kiwifruit*/
while loop - while문
val items = listOf("apple", "banana", "kiwifruit")
var index = 0
while (index < items.size) {
println("item at $index is ${items[index]}")
index++
}
/*item at 0 is apple
item at 1 is banana
item at 2 is kiwifruit*/
when Expression - when 표현식
약간 switch문과 비슷한 것 같다. describe 함수 인자로 어떤 값이든 받을 수 있고, 그 값이 해당하는 조건의 리턴 값을 출력한다.
fun describe(obj: Any): String =
when (obj) {
1 -> "One"
"Hello" -> "Greeting"
is Long -> "Long"
!is String -> "Not a string"
else -> "Unknown"
}
fun main() {
println(describe(1)) //One
println(describe("Hello")) //Greeting
println(describe(1000L)) //Long
println(describe(2)) //Not a string
println(describe("other")) //Unknown
}
Ranges - 범위
아래 코드는 in 연산자를 사용하여 x 값이 범위 안에 있는지 체크할 수 있다.
fun main() {
val x = 10
val y = 9
if (x in 1..y+1) {
println("fits in range") //fits in range
}
}
! 연산자를 사용하여 범위를 벗어났는지도 체크할 수 있다.
fun main() {
val list = listOf("a", "b", "c")
if (-1 !in 0..list.lastIndex) {
println("-1 is out of range") //-1 is out of range
}
if (list.size !in list.indices) {
println("${list.size} !in ${list.indices}") //3 !in 0..2
}
}
for문과 함께 범위 연산자를 사용할 수 있다.
fun main() {
for (x in 1..5) {
print(x) //12345
}
}
step 키워드를 사용하여 원하는 만큼 건너뛸 수 있다.
fun main() {
for (x in 1..10 step 2) {
print(x) //13579
}
println()
for (x in 9 downTo 0 step 3) {
print(x) //9630
}
}
Collections - 컬렉션
in 연산자를 사용해서 컬렉션 안에 해당 객체가 포함되어 있는지 확인할 수 있다.
fun main() {
val items = setOf("apple", "banana", "kiwifruit")
when {
"orange" in items -> println("juicy")
"apple" in items -> println("apple is fine too")
} //apple is fine too
}
lambda 표현식을 사용해서 컬렉션을 필터링하고 매핑할 수 있다. 이때, 컬렉션의 객체는 it 키워드로 표기한다.
fun main() {
val fruits = listOf("banana", "avocado", "apple", "kiwifruit")
fruits
.filter { it.startsWith("a") }
.sortedBy { it }
.map { it.uppercase() }
.forEach { println(it) } //APPLE\nAVOCADO
}
Nullable values and null checks - Null 허용 값과 null 값 검사
null 값이 가능한 경우 참조는 명시적으로 nullable로 표시되어야 한다. nullable로 표시하려면 타입 뒤에 ?를 넣어준다.
fun parseInt(str: String): Int? {
// ...
}
nullable 값을 반환하는 함수는 아래 코드와 같이 사용할 수 있다.
fun printProduct(arg1: String, arg2: String) {
val x = parseInt(arg1)
val y = parseInt(arg2)
if (x != null && y != null) {
println(x * y)
}
else {
println("'$arg1' or '$arg2' is not a number")
}
}
Type checks and automatic casts - 타입 검사 및 자동 캐스팅
is 연산자는 객체가 해당 타입이 맞는지 확인한다. 특정 타입에 대해 체크가 되면 이는 명시적으로 캐스팅할 필요가 없다. 하지만 체크가 되지 않으면 여전히 타입 추론이 불가하다.
fun getStringLength(obj: Any): Int? {
if (obj is String) {
// 여기서의 obj 타입은 String으로 자동 캐스팅 된다.
return obj.length
}
// 여기서의 obj 타입은 Any이다
return null
}
fun getStringLength(obj: Any): Int? {
if (obj !is String) return null
//obj는 위의 조건에 해당하지 않으므로 String으로 자동 캐스팅된다.
return obj.length
}
fun getStringLength(obj: Any): Int? {
// obj는 is 연산자를 통해 String으로 자동 캐스팅되므로 && 뒤의 조건식을 수행할 수 있다.
if (obj is String && obj.length > 0) {
return obj.length
}
return null
}
'프로그래밍 > Kotlin' 카테고리의 다른 글
Kotlin 배우기 (3) (0) | 2024.02.13 |
---|---|
Kotlin 배우기 (2) (1) | 2024.02.01 |
[Kotlin 기초 2] Objects (3) (9) | 2023.02.17 |
[Kotlin 기초 2] Objects (2) (6) | 2023.02.09 |
[Kotlin 기초 2] Objects (1) (4) | 2023.02.09 |
댓글