paint-brush
My first experiences with Kotlinby@mohsenoid
2,906 reads
2,906 reads

My first experiences with Kotlin

by Mohsen MirhoseiniMay 7th, 2017
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

<a href="https://kotlinlang.org" target="_blank">Kotlin</a> is a new language which at least most of Android developers heard about it or are using it instead of <a href="https://hackernoon.com/tagged/java" target="_blank">Java</a>.

People Mentioned

Mention Thumbnail
Mention Thumbnail

Company Mentioned

Mention Thumbnail
featured image - My first experiences with Kotlin
Mohsen Mirhoseini HackerNoon profile picture

some quick notes that might comes handy for beginners

Kotlin is a new language which at least most of Android developers heard about it or are using it instead of Java.

Out of my curiosity start learning it to know what’s attractive inside that makes some developer crazy about it! so during my learning process, I have made some notes which might look too minified but contains keywords for beginners and your later searches.

This is the notes which I prefer to have at the beginning of my learning process:

Variables:

val immutableName: String = "Mohsen"


var mutableName: String = "Mohsen"var mutableName = "Mohsen"

var nullableName: String? = null


val numbers = arrayListOf(1, 2, 3, 4, 5)print("Even Numbers are ${numbers.filter { i -> i % 2 == 0 }}")

val countries = listOf(Pair("Iran", "Tehran"), Pair("France", "Paris"), Pair("Germany", "Berlin"))



for ((country, city) in countries) {print("Country: $country - City: $city")}

Functions:

// fun stands for function!






fun addNumbers(first: Int, second: Int): Int {return first + second}addNumbers(10, 20)addNumbers(first = 10, second = 20)addNumbers(second = 1, first = 2) // !!!





// you can have multiple paramsfun addNumbers(vararg numbers: Int): Int {return numbers.sum()}addNumbers(1, 2, 3, 4, 5, 6)





// default valuefun addTwoNumbers(first: Int, secound: Int = 0): Int {return first + secound}addTwoNumbers(2)

Classes:


// no fields in classes! only properties and functionsclass Customer(val id: Int = 0, var name: String) {

// secondary constructor  
constructor(id: Int) : this(id, "")  
  
// initialize method  
init() {  
}  
  
// public by default property  
val test = 0  
  
// visible inside Customer.kt  
private fun foo() {}  
  
// property is visible everywhere  
// setter is visible only in Customer.kt  
public var bar: Int = 5  
	private set  
  
// visible inside the same module  
internal val baz = 6  

}

Data Classes:


// mutable data classes similar to AutoValue library which provide equals, toString, copy, etc.data class Customer(val id: Int = 0, var name: String)

Extension Function:



fun String.convertSpacesToUnderscores(): String {return this.replace(" ", "_")}

print("This is my sample String.".convertSpacesToUnderscores())

Null:


val x: String = null //error!val x: String? = null


// if x is not null range to 10x?.rangeTo(10)

Let:





var customer: Customer? = nullcustomer?.let {// it = user and not null and only read once!println(it.name)}



someMethod().let { result ->//method only run once!}

Any:

fun getStringLen(obj: Any): Int? = if (obj is String) obj.length else null

Companion:


// the same as Static methods and you have to access the// method like this: Customer.Companion.what()







class Customer {companion object {fun what(customer: Customer): String {return customer.id.toString() + customer.name}}}











// If you want the function looks like java static methods// like this: Customer.what() have to add JvmStatic// It is useful for calling static methods from NDK librariesclass Customer {companion object {@JvmStaticfun what(customer: Customer): String {return customer.id.toString() + customer.name}}}

Package function:


// functions with no classes, just the same as java import staticpackage com.google.test



fun packageFunction() {println("I am a package function!!")}

List, ArrayList, Map:


val list = listOf("a", "b")val mutableList = mutableListOf("a", "b")



for (s in list) {// ...}


val map = mapOf("key" to "value")val mutableMap = mutableMapOf("key" to "value")



for ((key, value) in map) {// ...}

Interfaces:


interface TestInterface {fun run(t:Int): String

fun test(){  
	// default body!  
}  

}

Generic:




class Box<T>(t: T) {// ...}Val box: Box(1) // box: Box<Int>

Enums:



enum class Direction(val degree: Int) {NORTH(0), EAST(90), SOUTH(180), WEST(270)}

Type Casting:


val y = x as Intval y = x as? Int // nullable



// smart castIf (x is String)x.toUpperCase()

Operator Overloading:

operator fun plus(other: Point): Point = Point(x + other.x, y + other.y)

Inheritance:



// all classes are final by default and for inheritance should be openopen class Shape {}


class Circle: Shape() {}

infix:



infix fun String.hello(name:String): String{return "Hello, $name. $this"}

"Test" hello "test" // == "Test".hello("test")

Delegates:




interface Repository<T : Record> {fun getById(id: Int): Tfun getAll(): List<T>}




class Controller(repository: Repository<Customer>) : Repository<Customer> by repository {fun customerList(): List<Customer> {return getAll()}

fun customerById(id: Int): Customer {  
	return getById(id)  
}  

}




var test: String by Delegates.observable("") {prop, old, new ->println("$old -> $new")}

Sealed:


// sealed means there is no PageResult child more than ones that are here in this filesealed class PageResult


class Success(val url: String) : PageResult()class Error(val code: Int, val message: String) : PageResult()


fun getPage(url: String): PageResult {val someOperationIsSuccessfull = false

if (someOperationIsSuccessfull)  
	return Success(url)  
else  
	return Error(404, "Not found")  

}







fun callingPage() {val result = getPage("http://google.com")when (result) {is Success -> println(result.url)is Error -> println(result.message)}}

Lazy:


class User(firstName: String, lastName: String) {val fullName: String by lazy { "$firstName $lastName" }

fun printFullName() {  
	println("User full name is: $fullName")  
}  

}

Local return:







fun myFunction() {val numbers = 1..100numbers.forEach {if(it%5==0)return@forEach} println("Hello!!") //Hello will be printed!}

Tailrec:






//tailrec convert a recursive function call to a goto looptailrec fun factorial(number: Int, accumulator: Int = 1): Int {when (number) {0 -> return accumulatorelse -> return factorial(number - 1, accumulator * number)}}

Some unusual syntaxes for Java developers!!:




// multiline string literalsprint("""1. test2. unit test3. what a test""")



print("""1. test2. unit test3. what a test""".trimIndent())



print("""|1. test|2. unit test|3. what a test""".trimMargin())

fun max(a: Int, b: Int) = if (a > b) a else b





// no for (int i=0;i<10;I++) loop!!!val myArray = arrayOf("A","B","C","D")for (index in 0 until myArray.size){println(myArray.get(index))}



for ( i in 1..10 )println(myArray.get(index))}



for ( i in 100 downTo 1 step 5)println(myArray.get(index))}



var i = 0while (i < 10)println (i++)








// no switch case defaultwhen (i) {0 -> println("zero")1..5 -> println("number")is String -> println("$i is string")!is String -> println("is not string")else -> println("unknown!!!")}




val isString = when ("Hello") {is String -> trueelse -> false}


val isInRange = i in 5..9val isMember = "hello" in array


// set alias while importing!Import com.google.Test as MyTest






// loop operatorswhile (true){if(false) breakif(false) continueif(false) return}






// labelsouter@ for (l in list) {for (m in map) {if (l == m.key) break@outer}}




// Pair and Triple data typesval myPair = Pair(1, "Mohse")val myTriple = Triple(1, "A", "Mohsen")val (id, name) = myPair




// measure runtime in ms!!val took = measureTimeMillis {// ...}





// deprecate a method@Deprecated ("Use another method!", level = WARNING/ERROR/HIDDEN, replaceWith = ReplaceWith("newPrintFullName()", imports = "com.google.test"))fun printFullName() {// …}





// rename method for Java@JvmName("methodNameInJava")fun printFullName() {// …}



// inject using qualifier annotation@field:[Inject ApplicationContext]lateinit var context: Context



// exclude field from serialization and gson@Transientvar id: String? = null

Kotlin Android Extensions:


// add plugin to build.gradleapply plugin: 'kotlin-android-extensions'

import kotlinx.android.synthetic.main.<layout>.*


// access views without findViewById!!myText.text = "Hello world!"

I look forward for your comments, experiences with Kotlin, and any unusual syntaxes which I might miss as a beginner. Share this article if you think it is useful by tapping 💚 button, and follow me for more articles Mohsen Mirhoseini.


Mohsen Mirhoseini_Senior Android Developer_mohsenoid.com