[Kotlin] Basic syntax 기초 구문
package 정의와 imports
package 사양은 소스파일의 최상단에 위치합니다.
이 때, 디렉토리와 패키지가 매치될 필요는 없습니다. 소스파일은 디렉토리와 상관없이 파일 시스템 어디든 위치할 수 있습니다.
package com.tistory.webfirewood.kotlin
import kotlin.text.*
// ...
program entry point
코틀린의 시작점(entry point)은 main 함수 입니다.
fun main() {
println("Hello world!")
}
또다른 형태의 main 함수는 복수의 String arguments를 받을 수 있습니다.
fun main(args: Array<String>) {
println(args.contentToString())
}
standard output
print 함수는 argument 를 standard output 으로 출력합니다.
fun main() {
print("Hello ")
print("world!")
}
println 함수는 argument를 출력하고 뒤에 line break를 추가합니다. 그래서 다음 출력은 다음 라인에 나타나게 됩니다.
fun main() {
println("Hello world!")
println(32)
}
함수
두 Int 파라미터를 받아서 Int 값을 리턴하는 함수
fun sum(a: Int, b: Int): Int {
return a + b
}
fun main() {
println("sum of 3 and 5 is ")
println(sum(3, 5))
}
이때, 리턴타입이 추론된다면 생략할 수 있습니다.
fun sum(a: Int, b: Int) = a + b
fun main() {
println("sum of 11 and 21 is ${sum(11, 21)}")
}
리턴타입이 의미없는 값인 경우
fun printSum(a: Int, b: Int): Unit {
println("sum of $a and $b is ${a + b}")
}
fun main() {
printSum(3, 4)
}
이 때, Unit 역시 생략 가능합니다.
변수
읽기 전용 지역 변수는 val 키워드로 정의한다. 이것들은 딱 한번만 값이 할당됩니다.
fun main() {
val a: Int = 1 // 즉시 할당
val b = 2 // Int 타입이 추론 된다
val c: Int // 값이 초기화 되지 않으면 타입이 필요
c = 3
println("a = $a, b = $b, c = $c")
}
재할당 가능한 변수는 var 키워드로 선언합니다.
fun main() {
var x = 5;
x += 1;
println("x = $x")
}
클래스와 인스턴스
클래스를 선언하기 위해서 class 키워드를 사용합니다. 클래스의 속성은 선언문이나 바디에 선언할 수 있습니다.
class Rectangle(var height: Double, var length: Double) {
var perimeter = (height + length) * 2
}
fun main() {
val rectangle = Rectangle(5.0, 2.0)
println("The perimeter is ${rectangle.perimeter}")
}
클래스 사이의 상속은 콜론 ':' 으로 정의합니다. 상속할 수 있는 클래스를 만들기 위해서 open 을 표시합니다.
open class Shape
class Rectangle(var height: Double, var length: Double): Shape() {
var perimeter = (height + length) * 2
}
조건문
조건문은 다른 언어와 유사하지만 코틀린에서는 if 를 표현식으로 쓸 수 있습니다.
fun maxOf(a: Int, b: Int) = if (a > b) a else b
fun main() {
println("max of 0 and 42 is ${maxOf(0, 42)}")
}
for loop
fun main() {
val items = listOf("apple", "banana", "kiwifruit")
for (item in items) {
println(item)
}
}
또는
fun main() {
val items = listOf("apple", "banana", "kiwifruit")
for (index in items.indices) {
println(items[index])
}
}
when 표현식
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))
println(describe("Hello"))
println(describe(1000L))
println(describe(2))
println(describe("other"))
}
ranges
만약 숫자가 어떤 범위 안에 있는지 확인하고 싶을때 in 연산자를 씁니다. (Collections 에서도 사용법이 같습니다.)
fun main() {
val x = 10
val y = 9
if (x in 1..y+1) {
println("fits in range")
}
}
fun main() {
val list = listOf("a", "b", "c")
if ("a" in list) {
println("a is in list.")
}
}
for 문에서도 in 연산자를 사용합니다.
fun main() {
for (x in 1..5) {
print(x)
}
println()
for (x in 1..10 step 2) {
print(x)
}
println()
for (x in 9 downTo 0 step 3) {
print(x)
}
}
Nullable
null 값이 들어올 수 있는 변수는 타입 끝에 '?' 를 붙여서 표시합니다.
반환값이 null 또는 Int 일 수 있는 함수의 경우 다음과 같습니다.
fun parseInt(str: String): Int? {
// ...
}
타입체크와 자동 캐스트
is 연산자는 ㅍ현식이 어떤 인스턴스 타입인지 체크합니다.
fun getStringLength(obj: Any): Int? {
if (obj is String) {
// 이 분기에서 obj 는 자동으로 String 으로 캐스트 됩니다.
return obj.length;
}
// 분기 밖에서 obj는 여전히 Any 타입입니다.
return null;
}