Getting Started Kotlin
Learn the basics of getting started with kotlin
--->>> Repo: Kotlin Koans <<<---
--->>> Repo: Problems Kotlin <<<---
--->>> Repo: GameBoy Emulator Enviroment <<<---
--->>> Repo: Kotlin Mobile <<<---
--->>> Repo: Kotlin JavaScript <<<---
--->>> Repo: Kotlin Native - iOS <<<---
--->>> Repo: Ktor Examples <<<---
Indexes
- Hello World
- Basic Variables
- Static Values
- Strings
- Boolean Operators
- Conditional
- Control Flow
- Constructors
- Basic Functions
- Basic Classes
- Data Classes
- Singleton Class
- Properties
- Interface
- Herencia
- Extension Function Basics
- Null Safety
- Infix Function
Hello World
Main.kt
fun main(args: Array<String>) {
val printHelloWorld = PrintHelloWorld()
basic(printHelloWorld)
basicEmpty(printHelloWorld)
empty(printHelloWorld)
}
private fun empty(printHelloWorld: PrintHelloWorld) {
printHelloWorld.empty()
}
private fun basicEmpty(printHelloWorld: PrintHelloWorld) {
printHelloWorld.basicEmpty()
}
private fun basic(printHelloWorld: PrintHelloWorld) {
val name = "Victor"
printHelloWorld.basic(name)
}
PrintHelloWorld.kt
public class PrintHelloWorld{
companion object { val HELLO_WORLD = "Hello World " }
public fun basic(name:String){
println(HELLO_WORLD+name)
}
public fun basicEmpty(name:String = ""){
println(HELLO_WORLD+name)
}
public fun empty(){
println(HELLO_WORLD)
}
}
Result
Hello World Victor
Hello World
Hello World
Basic Variables
Main.kt
fun main(args: Array<String>) {
immutableValue()
mutableValue()
nullableValue()
}
private fun immutableValue() {
val name = "Victor"
//immutable prototype
//val name : String = "Victor"
// name = "Victor Manuel" Error!
println(name)
}
private fun mutableValue() {
//mutable prototype
var lastName: String
lastName = "Victor Bolinches"
println(lastName)
}
private fun nullableValue() {
//var lastNameNullable: String Error!
//lastNameNullable = null Error!
var lastNameNullable: String?
lastNameNullable = null
println(lastNameNullable)
lastNameNullable = "Victor Manuel Bolinches"
println(lastNameNullable)
}
Result
Victor
Victor Bolinches
null
Victor Manuel Bolinches
Static Values
Main.kt
fun main(args: Array<String>) {
start()
stop()
}
fun start() = println("State static: ${State.START}")
fun stop() = println("State static: ${State.STOP}")
State.kt
public class State {
companion object {
val START = 1
val STOP = 0
}
}
Result
State static = 0
State static = 1
Strings
Main.kt
fun main(args: Array<String>) {
literals()
templates()
}
private fun templates() {
val number = 18
val name = "vicboma $number"
println(name)
println("$name.length = ${name.length}")
val price = "${'$'}9.99 = 9.99 dollars"
println(price)
}
private fun literals() {
val helloWorld = "Hello, world!"
println(helloWorld)
val str = "Hello, world!\n..." // w/backslash
println(str)
}
Result
Hello, world!
Hello, world!
...
vicboma 18
vicboma 18.length = 10
$9.99 = 9.99 dollars
Boolean Operators
Main.kt
fun main(args: Array<String>) {
disjunction()
conjunction()
negation()
}
private fun negation() {
val list = arrayOf(
BooleanOperator.negation(false),
BooleanOperator.negation(true)
)
printlnResult(list)
}
private fun conjunction() {
val list = arrayOf(
BooleanOperator.lazyConjunction(false, false),
BooleanOperator.lazyConjunction(false, true),
BooleanOperator.lazyConjunction(true, false),
BooleanOperator.lazyConjunction(true, true)
)
printlnResult(list)
}
private fun disjunction() {
val list = arrayOf(
BooleanOperator.lazyDisjunction(false, false),
BooleanOperator.lazyDisjunction(false, true),
BooleanOperator.lazyDisjunction(true, false),
BooleanOperator.lazyDisjunction(true, true)
)
printlnResult(list)
}
fun printlnResult(values:Array<Boolean>){
for(x in values){
println(x)
}
}
BooleanOperator.kt
class BooleanOperator{
companion object {
fun lazyDisjunction(cond1: Boolean, cond2: Boolean) = cond1 || cond2
fun lazyConjunction(cond1: Boolean, cond2: Boolean) = cond1 && cond2
fun negation(cond1: Boolean) = !cond1;
}
}
Result
//Disjunction
false false = false
false true = true
true false = true
true true = true
//Conjunction
false false = false
false true = false
true false = false
true true = true
//Negation
false = true
true = false
Conditional
Main.kt
fun main(args: Array<String>) {
val math : Math = Math()
max(math)
min(math)
maxIn(math)
minIn(math)
lambdas(math)
}
private fun lambdas(math: Math) {
val maxLambda: (Int, Int) -> Int = { x, y -> if (x > y) x else y }
val minLambda: (Int, Int) -> Int = { x, y -> if (x > y) y else x }
val inFunctionMax = math.inFunction(100, 3, maxLambda)
val inFunctionMin = math.inFunction(100, 3, minLambda)
println(inFunctionMax)
println(inFunctionMin)
}
private fun minIn(math: Math) {
val minIn = math.minIn(4, 1)
val minIn1 = math.minIn(4, 4)
println(minIn)
println(minIn1)
}
private fun maxIn(math: Math) {
val maxIn = math.maxIn(3, 6)
println(maxIn)
}
private fun min(math: Math) {
val min = math.min(8, 0)
println(min)
}
private fun max(math: Math) {
val max = math.max(6, 7)
println(max)
}
Math.kt
class Math {
fun max(a: Int, b: Int): Int {
if (a > b) {
return a
} else {
return b
}
}
fun min(a: Int, b: Int): Int {
if (a > b) {
return b
} else {
return a
}
}
fun maxIn(a: Int, b: Int): Int = if(a > b) a else b
fun minIn(a: Int, b: Int): Int = if (a > b) b else a
//val max : (Int, Int) -> Int = { x , y -> if (x > y) x else y }
//val min : (Int, Int) -> Int = { x , y -> if (x > y) y else x }
fun inFunction(x : Int, y : Int, f:(Int, Int) -> Int) : Int {
return f(x,y)
}
}
Result
7
0
6
1
100
3
4
Control Flow
While
Main.kt
fun main(args: Array<String>) {
ArrayWithIterator()
ArrayDoWhile()
classic()
}
private fun ArrayDoWhile() {
var arraySafety = arrayOf<Any?>(1, 2, 3, 4, 5, null)
doWhile(arraySafety)
}
private fun ArrayWithIterator() {
var arrayAny = arrayOf(1, 2, 3, 4, 5)
withIterator(arrayAny)
}
private fun classic() {
var i = 5
while (0 <= i) {
println(i--)
}
}
private fun doWhile(arraySafety: Array<Any?>) {
val iterator = arraySafety.iterator()
do {
val y = iterator.next()
println(y)
} while (y != null) // y is visible here!
}
private fun withIterator(arrayAny: Array<Int>) {
val iterator = arrayAny.iterator()
while (iterator.hasNext()) {
val next = iterator.next()
println(next)
}
}
Result
1
2
3
4
5
1
2
3
4
5
null
5
4
3
2
1
0
For
Main.kt
fun main(args: Array<String>) {
var arrayAny = arrayOf(12,2.3,45F,"Soy una String",true, null)
anIterator(arrayAny)
withBodyBlock(arrayAny)
withIndices(arrayAny)
}
private fun withIndices(arrayAny: Array<Any?>) {
for (i in arrayAny.indices)
println(arrayAny[i])
}
private fun anIterator(arrayAny: Array<Any?>) {
for (any in arrayAny)
println(any)
}
private fun withBodyBlock(arrayAny: Array<Any?>) {
for (any: Any? in arrayAny) {
print(any)
print("\n")
}
}
Result
12
2.3
45.0
Soy una String
true
null
12
2.3
45.0
Soy una String
true
null
12
2.3
45.0
Soy una String
true
null
When
Main.kt
fun main(args: Array<String>) {
var array = arrayOf(1,2,3)
forWhenDefault(array)
forWhenCombined(array)
forImplicitCast()
expression()
}
private fun expression() {
var arrayNumber = arrayOf(1, 2, 19, 20, 14, 35, 45)
expression(arrayNumber)
}
private fun forImplicitCast() {
var arrayAny = arrayOf<Any?>(1, 2.0, 5F, "", true)
implicitCasts(arrayAny)
}
private fun forWhenCombined(array: Array<Int>) {
for (i in array)
whenCombined(i)
}
private fun forWhenDefault(array: Array<Int>) {
for (i in array)
_whenDefault(i)
}
/**
* We can also check a value For being in or !in a range or a collection:
*/
private fun expression(arrayNumber: Array<Int>) {
val validNumbers = arrayOf(35)
for (obj in arrayNumber)
when (obj) {
in 1..10 -> println("x is in the range")
in validNumbers -> println("x is valid")
!in 10..20 -> println("x is outside the range")
else -> println("none of the above")
}
}
/**
* with patter matching
*/
private fun implicitCasts(arrayAny: Array<Any?>) {
for (obj in arrayAny)
when (obj) {
is String -> println("is String")
is Int -> println("is Int")
is Float -> println("is Float")
is Double -> println("is Double")
!is Boolean -> println("is not Boolean")
else -> println("is Boolean ")
}
}
/**
* If many cases should be handled in the same way, the branch conditions may be combined with a comma
*/
private fun whenCombined(i: Int) {
when (i) {
0, 1 -> println("x == 0 or x == 1")
else -> println("otherwise")
}
}
/**
* when replaces the switch operator of C-like languages
* when can be used either as an expression or as a statement
*/
private fun _whenDefault(x: Int) {
when (x) {
1 -> println("x == 1")
2 -> println("x == 2")
else -> {
// Note the block
println("x is neither 1 nor 2")
}
}
}
Result
x == 1
x == 2
x is neither 1 nor
x == 0 or x == 1
otherwise
otherwise
is Int
is Double
is Float
is String
is Boolean
x is in the range
x is in the range
none of the above
none of the above
none of the above
x is valid
x is outside the range
Return and Jump
Kotlin has three structural jump operators
-
- return. By default returns from the nearest enclosing function or function expression.
- — break. Terminates the nearest enclosing loop.
-
- continue. Proceeds to the next step of the nearest enclosing loop.
fun main(args: Array<String>) {
returnBasic()
inlineReturn()
implicitReturn()
breakLoopContinue()
}
private fun implicitReturn() {
println("Init implicit return")
listOf(1, 2, 3, 4, 5).forEach {
if (it == 2) {
println("Exit implicit return")
return@forEach
}
println(it)
}
}
private fun inlineReturn() {
println("Init inline return")
listOf(1, 2, 3, 4, 5).forEach lit@ {
if (it == 5) {
println("Exit inline return")
return@lit
}
println(it)
}
}
private fun returnBasic(): Unit {
println("Init Basic return")
for (i in 0..5) {
if (i == 5) {
println("Exit Basic return")
return
}
println(i)
}
}
private fun breakLoopContinue() {
println("Init Basic Loop")
Continue@ for (i in 1..100) {
for (j in 1..100) {
if (j === 50) {
break@Continue
}
}
}
println("Exit Basic Loop")
}
Result
//returnBasic
Init Basic return
0
1
2
3
4
Exit Basic return
//inlineReturn
Init inline return
1
2
3
4
Exit inline return
//implicitReturn
Init implicit return
1
Exit implicit return
3
4
5
//breakLoopContinue
Init breakLoopContinue Loop
Exit breakLoopContinue Loop
Constructors
Primary
class MyView (ctx: Context): View(ctx) {
...
}
Secundary
class MyView : View {
constructor(ctx: Context) : super(ctx)
constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs)
}
Internal
class MyView internal constructor(ctx: Context) : View (ctx) {
...
}
Basics Functions
Main.kt
fun main(args: Array<String>) {
val numberOperations = NumberOperations()
twoNumbers(numberOperations)
twoNumberReverse(numberOperations)
addTwoNumbersDefault(numberOperations)
reverseList(numberOperations)
reverseList2(numberOperations)
sumLambda(numberOperations)
sumLambdainFunction(numberOperations)
sumInlineOperation(numberOperations)
}
private fun sumInlineOperation(numberOperations: NumberOperations) {
val sumInFunction = numberOperations.sumInFunction(5, 9, { x, y -> x + y })
println(sumInFunction)
}
private fun sumLambdainFunction(numberOperations: NumberOperations) {
val _sumLambda: (Int, Int) -> Int = { x, y -> x + y }
val _sumInFunction = numberOperations.sumInFunction(9, 9, _sumLambda)
println(_sumInFunction)
}
private fun sumLambda(numberOperations: NumberOperations) {
val sumLambda = numberOperations.sumLambda(2, 2)
println(sumLambda)
}
private fun reverseList2(numberOperations: NumberOperations) {
val reverseList1 = numberOperations.reverseList(listOf(1, 2, 3, 4)).asList()
println(reverseList1)
}
private fun reverseList(numberOperations: NumberOperations) {
val reverseList = numberOperations.reverseList(arrayListOf(1, 2, 3)).asList()
println(reverseList)
}
private fun addTwoNumbersDefault(numberOperations: NumberOperations) {
val addTwoNumbersDefault = numberOperations.addTwoNumbersDefault(2)
println(addTwoNumbersDefault)
}
private fun twoNumbers(numberOperations: NumberOperations) {
val addTwoNumbers = numberOperations.addTwoNumbers(first = 2, second = 5)
println(addTwoNumbers)
}
private fun twoNumberReverse(numberOperations: NumberOperations) {
val addTwoNumbers1 = numberOperations.addTwoNumbers(second = 5, first = 2)
println(addTwoNumbers1)
}
NumberOperations.kt
public class NumberOperations{
fun addTwoNumbers(first:Int, second :Int) : Int {
val result = first + second
return result
}
fun addTwoNumbersDefault(first:Int, second :Int = 0) : Int {
val result = first + second
return result
}
inline fun reverseList<reified T>(list : List<T>) : Array<T> {
return list.reversed().toTypedArray();
}
Funciones de Orden Superior y Expresiones Lambda (como en Haskell :D)
val sumLambda : (Int, Int) -> Int = { x,y -> x + y}
fun sumInFunction(x : Int, y : Int, f:(Int, Int) -> Int) : Int {
return f(x,y)
}
}
Result
5 + 2 = 7
2 + 5 = 7
2 + 0 = 2
[1, 2, 3] = [3, 2, 1]
[1, 2, 3, 4] = [4, 3, 2, 1]
2 + 2 = 4
9 + 9 = 18
5 + 9 = 14
Basic Classes
Main.kt
fun main(args: Array<String>) {
customerMethod()
employeeMethod()
}
private fun employeeMethod() {
val employee = Employee(1221, "Vicboma")
val toString = employee.toString()
val id = employee.id
val name = employee.name
println("Id : $id Name: $name")
println("Employee ToString: $toString")
println(employee)
}
private fun customerMethod() {
val customer = Customer(1234)
customer.doSomething();
val toString = customer.toString();
val id = customer.id;
println("Customer id: $id");
println("Customer ToString: $toString");
}
Customer.kt
public class Customer(_id : Int) {
val id = _id;
//prototype
var name : String? = ""
fun doSomething(){
println("Some code")
}
override fun toString() : String
{
return ""+this.id;
}
}
Employee.kt
public class Employee( val id : Int, val name: String ) {
}
Result
Some code
Customer id: 1234
Customer ToString: 1234
Id : 1221 Name: Vicboma
Employee ToString: Employee@4cc77c2e
Data Classes
Main.kt
fun main(args: Array<String>) {
templateExamples()
}
private fun templateExamples() {
val customer1 = Customer(1, "victor", "[email protected]")
val customer2 = Customer(1, "victor", "[email protected]")
val customer3 = customer1;
val dataCustomer4 = DataCustomer(1, "victor", "[email protected]")
val dataCustomer5 = dataCustomer4;
println(customer1) //toString
println(customer1.hashCode()) //hashCode
println(customer1.equals(customer2)) //equals()
println(customer1.equals(customer3))
//The compiler automatically derives the following members from all properties declared in the primary constructor:
//equals()/hashCode() pair,
//toString() of the form "User(name=John, age=42)",
//componentN() functions corresponding to the properties in their order or declaration,
//copy() function (see below).
println(dataCustomer4.equals(dataCustomer5))
println(dataCustomer4)
}
Customer.kt
public class Customer(val id : Int, val name : String, val email : String) {
}
DataCustomer.kt
/**
* The primary constructor needs to have at least one parameter;
* All primary constructor parameters need to be marked as val or var;
* Data classes cannot be abstract, open, sealed or inner;
* Data classes may not extend other classes (but may implement interfaces).
*/
data public class DataCustomer(val id : Int, val name : String, val email : String) {
}
Result
Customer@4cc77c2e
1288141870
false
true
true
DataCustomer(id=1, name=victor, [email protected])
Singleton Class
public class Singleton {
private String b;
private static Singleton instance;
private Singleton() {
System.out.println("This "+this+" is a singleton")
}
public static Singleton getInstance() {
if (instance == null)
instance = new Singleton();
return instance;
}
public void setB(String b) { this.b = b;}
public String getB() { return this.b; }
}
---------
final Singleton first = new Singleton()
first.setB("hello singleton"=
String second = new Singleton()
println(second.getB())
object Singleton {
init {
println("This ($this) is a singleton")
}
var b:String? = null
}
---------
var first = Singleton
first.b = "hello singleton"
var second = Singleton
println(second.b)
Result
This (Singobj@728938a9) is a singleton
hello singleton
Properties
class Rectangle(val height: Int, val width: Int) {
val isSquare: Boolean
get() = (height == width)
set(value)
field = value
}
Interface
Main.kt
fun main(args: Array<String>) {
val z = Z("I am Z")
val zToString = z.toString()
println(zToString)
val zFizz = z.fiz()
println(zFizz)
val zBuzz = z.buzz()
println(zBuzz)
}
X.kt
interface X{
fun fiz() : String
}
A.kt
interface A{
fun buzz() :String
}
Z.kt
open class Z(val arg:String) : A, X {
override fun toString() = "ToString() : $arg"
override fun fiz() : String = "Z - fiz"
override fun buzz() : String = "Z - buzz"
}
Result
ToString() : I am Z
Z - fiz
Z - buzz
Herencia
Main.kt
fun main(args: Array<String>) {
val b = B("I am B")
val bToString = b.toString()
println(bToString)
val bFizz = b.fiz()
println(bFizz)
val bBuzz = b.buzz()
println(bBuzz)
val bValue = b.fizBuzz
println("b.class.toString() $bValue")
val c = C()
val cToString = c.toString()
println(cToString)
val cFizz = c.fiz()
println(cFizz)
val cBuzz = c.buzz()
println(cBuzz)
val cValue = c.fizBuzz
println("c.class.toString() $cValue")
val h = H("I am H")
val hToString = h.toString()
println(cToString)
val hFizz = h.fiz()
println(hFizz)
val hBuzz = h.buzz()
println(hBuzz)
}
X.kt
interface X{
fun fiz() : String
}
A.kt
interface A{
fun buzz() :String
}
Z.kt
open class Z(val arg:String) : A, X {
override fun toString() = "ToString() : $arg"
override fun fiz() : String = "Z - fiz"
override fun buzz() : String = "Z - buzz"
}
B.kt
class B(val name:String) : Z("Z"), W {
override val fizBuzz : Int = 29
override fun fiz() : String = "B - fiz"
override fun buzz() : String = "B - buzz"
override fun toString() : String = "ToString() : ${this.name} and my parent is ${super.toString()}"
}
C.kt
class C : Z("I am Z"), W {
override val fizBuzz : Int = 92
override fun fiz() : String = "C - fiz"
override fun buzz() : String = "C - buzz"
}
H.kt
class H(val name:String):Z("I am Z") {
override fun fiz() :String = super.fiz()
override fun buzz() : String = super.buzz()
}
Result
ToString() : I am B and my parent is ToString() : Z
B - fiz
B - buzz
b.class.toString() 29
ToString() : I am Z
C - fiz
C - buzz
c.class.toString() 92
ToString() : I am Z
Z - fiz
Z - buzz
Extension Function Basics
Main.kt
fun main(args: Array<String>) {
val str = functionClassic()
functionInvokeInstance(str)
}
private fun functionInvokeInstance(str: String) {
val convertSpacesToUnderscoresInvokeInstanceString = str.convertSpacesToUnderscoresInvokeInstanceString()
println(convertSpacesToUnderscoresInvokeInstanceString)
}
private fun functionClassic(): String {
val str = "this is my text"
val convertSpacesToUnderscores = convertSpacesToUnderscores(str);
println(convertSpacesToUnderscores)
return str
}
fun convertSpacesToUnderscores(str: String) : String {
return str.replace(" ","_")
}
fun String.convertSpacesToUnderscoresInvokeInstanceString() : String {
return this.replace(" ","_")
}
Result
function: this_is_my_text
Invoke Instance String: this_is_my_text
Null Safety
Main.kt
fun main(args: Array<String>) {
checkingForNullcondition()
val listMutable = safetyAccess()
elvisOperator(listMutable)
safetyCasts()
specialOperator()
}
private fun specialOperator() {
val str: String? = null
val len = str!!.length //accedemos a la propiedad, pero dará una excepción.
}
private fun safetyCasts() {
val a: Double = 2.0
val aInt: Int? = a as? Int
println(aInt)
}
private fun elvisOperator(listMutable: Array<Int>) {
val result = listMutable?.size ?: -1
println(result)
}
//Safe Calls - Any"?".property
private fun safetyAccess(): Array<Int> {
val listMutable = arrayOf(1, 2, 3, 4)
val _size = listMutable?.size
if (listMutable != null && _size > 0)
println("Array of size $_size")
else
println("Empty Array")
return listMutable
}
private fun checkingForNullcondition() {
val listImmutable = listOf(1, 2, 3, 4)
val size = listImmutable.size
if (listImmutable != null && size > 0)
println("Array of size $size")
else
println("Empty Array")
}
Result
Array of size 4
Array of size 4
4
null
Exception in thread "main" kotlin.KotlinNullPointerException
at MainNullsafetyOperatorsKt.main(mainNullsafetyOperators.kt:39)
Infix Function
Main.kt
fun main(args: Array<String>) {
val list = listOf(10, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5)
doubleResult(list)
filter(list)
map(list)
}
//infix without paren + brace
private fun map(list: List<Int>) = list.filter{ it % 2 == 0 }.map{ it - 1 }.forEach{ println(it) }
//infix without Dots & paren + brace
private fun filter(list: List<Int>) = list filter { it % 2 == 0 } forEach { println(it) }
//infix with paren & brace
private fun doubleResult(list: List<Int>) = list.forEach({ println(it * 2) })
Result
20
-10
-8
-6
-4
-2
0
2
4
6
8
10
10
-4
-2
0
2
4
9
-5
-3
-1
1
3
Reference:
- Main : http://kotlin.es
- Facebook : https://www.facebook.com/kotlin.es
- Video tutorials: https://kotlinlang.org/docs/videos.html
- Manual: https://kotlinlang.org/docs/kotlin-docs.pdf
- @Author: Victor Bolinches Marin