kotlin basic syntax official docs
해당 문서 공부 + 정리
kotlin 서론, 요약본 같은 느낌인데 복습에 좋을 듯 하다.
일단 세미콜론은 필요없다. 여러line을 한 line으로 합칠때 사용할 수 있다.
Package specification should be at the top of the source file.
package my.demo
import kotlin.text.*
fun printMessage() { /*...*/ }
class Message { /*...*/ }
//...
All the contents, such as classes and functions, of the source file are included in this package.
So, in the example above, the full name of printMessage() is org.example.printMessage, and the full name of Message is org.example.Message.
It is not required to match directories and packages: source files can be placed arbitrarily in the file system.
This means that you can place a Kotlin file with a specific package name in any directory.
If the package is not specified, the contents of such a file belong to the default package with no name.
about kotlin package
An entry point of a Kotlin application is the main function.
fun main() {
println("Hello world!")
}
...
fun main(args: Array<String>) {
println(args.contentToString())
}
main fun can accept a variable number of String arguments.
print("Hello ")
print("world!")
//Hello world!
println("Hello ")
println("world!")
//Hello
//world!
println adds a line break.
fun sum(a: Int, b: Int): Int {
return a + b
}
//function body can be an expression.
fun sum(a: Int, b: Int) = a + b
// returning no meaningful value
fun printSum(a: Int, b: Int): Unit {
println("sum of $a and $b is ${a + b}")
}
//unit return type can be omitted.
fun printSum(a: Int, b: Int) {
println("sum of $a and $b is ${a + b}")
}
Read-only local variables are defined using the keyword val.(can be assigned only once.)
Variables that can be reassigned use the var keyword.
val a: Int = 1 // immediate assignment
val b = 2 // `Int` type is inferred
// deferred assignment
// Type required when no initializer is provided
val c: Int
c = 3
var x = 5 // `Int` type is inferred
x += 1
To define a class, use the class keyword
//Properties of a class can be listed in its declaration or body.
class Rectangle(var height: Double, var length: Double) {
var perimeter = (height + length) * 2
}
//The default constructor with parameters listed in the class declaration is available automatically.
val rectangle = Rectangle(5.0, 2.0)
println("The perimeter is ${rectangle.perimeter}")
Inheritance between classes is declared by a colon (:).
Classes are final by default.(a class, method, or property cannot be overridden or extended by subclasses.)
-> cannot be used as a base class for inheritance, and no subclass can be created from it.
to make a class inheritable, mark it as open.
open class Shape
class Rectangle(var height: Double, var length: Double): Shape() {
var perimeter = (height + length) * 2
}
// This is an end-of-line comment
/* This is a block comment
on multiple lines. */
var a = 1
// simple name in template:
val s1 = "a is $a"
a = 2
// arbitrary expression in template:
val s2 = "${s1.replace("is", "was")}, but now is $a"
//a was 1, but now is 2
a in s1 cannot be changed dynamically.
fun maxOf(a: Int, b: Int): Int {
if (a > b) {
return a
} else {
return b
}
}
// if can also be used as an expression.
fun maxOf(a: Int, b: Int) = if (a > b) a else b
val items = listOf("apple", "banana", "kiwifruit")
for (item in items) {
println(item)
}
for (index in items.indices) {
println("${items[index]}")
}
var index = 0
while (index < items.size) {
println("${items[index]}")
index++
}
//apple
//banana
//kiwifruit
fun describe(obj: Any): String =
when (obj) {
1 -> "One"
"Hello" -> "Greeting"
is Long -> "Long"
!is String -> "Not a string"
else -> "Unknown"
}
it seems like a kind of switch case.(definitly better than traditional switch case statement.)
'in' with '..' can be used as a range.
val x = 10
val y = 9
//number range(1~10)
if (x in 1..y+1) {
println("fits in range")
}
// index range
val list = listOf("a", "b", "c")
// 0..2
if (-1 !in 0..list.lastIndex) {
println("-1 is out of range")
}
// 3 !in 0..2
if (list.size !in list.indices) {
println("list size is out of valid list indices range, too")
}
//iteration
for (x in 1..5) {
print(x) //12345
}
for (x in 1..10 step 2) {
print(x) //13579
}
for (x in 9 downTo 0 step 3) {
print(x) //9630
}
val items = setOf("apple", "banana", "kiwifruit")
//iterate over a collection
for (item in items) {
println(item)
}
when {
"orange" in items -> println("juicy")
"apple" in items -> println("apple is fine too")
}
// lambda expression to filter
val fruits = listOf("banana", "avocado", "apple", "kiwifruit")
fruits
.filter { it.startsWith("a") }
// avocado, apple
.sortedBy { it }
// apple, avocado
.map { it.uppercase() }
// APPLE, AVOCADO
.forEach { println(it) }
'it' referes to the current element.
it is a shorthand notation in Kotlin for a lambda expression that takes a single argument.
A reference must be explicitly marked as nullable when null value is possible.
Nullable type names have ? at the end.
fun parseInt(str: String): Int? {
// ...
}
fun parseInt(str: String): Int? {
return str.toIntOrNull()
}
'is' operator checks the type of expression.
If the expression is the specified type, the is operator returns true. Otherwise, it returns false.
if an immutable local variable or property is checked for a specific type, there's no need to cast it explicitly.
fun getStringLength(obj: Any): Int? {
// `obj` is automatically cast to `String` on the right-hand side of `&&`
if (obj is String && obj.length > 0) {
return obj.length
}
return null
}
// there is no need to cast type explicitly.
// both are same.
val x: Any = "Hello"
if (x is String) {
val str = x as String
println(str.length)
}
val x: Any = "Hello"
if (x is String) {
println(x.length)
}