Skip to content

Instantly share code, notes, and snippets.

@anoop4real
Last active June 2, 2019 09:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anoop4real/d570af6bee1912650c7a6a9a2bd54a00 to your computer and use it in GitHub Desktop.
Save anoop4real/d570af6bee1912650c7a6a9a2bd54a00 to your computer and use it in GitHub Desktop.

KOTLIN -My Learnings

Now Kotlin is officially announced for Android, I thought of getting started and below is my learnings, as an iOS developer, I am writing a comparison also whereever required.

  • Leaner code, expressive

  • Kotlin is a statically typed programming language from JetBrains. (Type of a variable is known at compile time.)

  • Safe: Exceptions are caught at compile time. Type interpretation is also present for some types. Kotlin is null safe. (In Kotlin, the type system distinguishes between references that can hold null and those that cannot.)

  • Interoperable : Interoperable with Java and Android libs

  • REPL : Similar to Swift REPL, Kotlin also have an REPL where in which we can try out expressions.

  • Supports functional programming ( eg:Lambda functions)

var for variable, which is mutable and can be re-assigned. Similar in Swift also.

var text = "hello" // Here Kotlin finds out text is of String type.

We can explictly do this by giving the type name

var text:String = "hello"

var number = 5.45 // Interpreted as Double

var number:float = 5.45 // Gives error as by default decimals are interpretted as double. To fix it you need to append "f"

var number:float = 5.45f

val for constants, immutable. We use let in Swift.

const val constants which are assigned at compile time. Usually used when you need Constants

object Constants {
    const val BASE_URL = "http://myApi/"
}

Pairs is a data type in kotlin where we can have a generic pair of values. It is similar to Tuples in Swift

        val weapn = "Gun" to "Fire"
        print(weapn.first)
        print(weapn.second)

        val (weaponName, use) = weapn
        print(weaponName)
        print(use)
        

You can return more than one value from a function

    fun giveMeAWeapon():Pair<String, String>{

        val weapn = "Gun" to "Fire"

        return weapn
    }

Pairs can be converted to string and toList.

Triples hold or return three values.

    fun getStudentFullDetails():Triple<String, String, Int>{

        return Triple(firstName, lastName, age)
    }
    

Missing value, null safety. We cannot assign null to any basic data type var str:String = null = error

If you still want to create nullable you need to add ? to the type.

var str:String? = null This is similar to optionals in swift

If a variable is nullable you wont be able to call methods on it ie str.length will return error, we need to use ? here again str?.length will work fine here, if there is value in str it will return the length else it will return null If we are sure that the variable definitely contain a value then we can use !! ie str!!.length this is similar to forced unwrapping in swift, here if the value is null, we will get a null pointer exception.

Main

Entry point of the application.

if

Nothing new, same as normal if...else

val threshold = 200

if (threshold < 100){

    println("its good")
}else if (threshold > 100){
    println("need to worry")
}else if (threshold == 200){
    println("reached maximum")
}

When

Similar to if but we dont specify any condition.

val state: Int = 1

when (state){

    1 -> println("State is Running.")
    2 -> {
        // if there is multiple lines, use curly braces
        println("State is Stopped.")
    }
    // Any unsatisfied state
    else -> println("State is Stopped.")

}

Ranges

val random = Random().nextInt(30)
println(random)
when (random){
    in 1..10 -> {
        println(" value between 1 and 10")
    }
    in 11..20 -> {
        println(" value between 11 and 20")
    }
    else ->{
        println(" value above 20")
    }

}

    // Iterate revers

for (i in 4 downTo 1)
    print(i)

// Iterate with step

for (i in 1..4 step 2)
    print(i)

Type Check using is and !is Operators

if (a is String) {
    print(a.length)
}
if (a !is String) {
    print("a is not a String")
}

Smart Casts

if (a is String) {
    print(a.length) // val gets automatically cast to String
}

if (a !is String) return
print(a.length) // val gets automatically cast to String

// Usage with when
when (a) {
    is Int -> print(a + 1)
    is IntArray -> print(a.sum())
}

Type Casting : Unsafe Cast

val a: String = b as String

Type Casting : Safe Cast

val a: String? = b as? String
val array = arrayOf(1,2,3,4)
val mixedarray = arrayOf("String",1,2,false) // Any
val array2 = arrayOf(1,2,3,4)
val numbers = intArrayOf(1,2,3,4) // Only integers are possible

//Combine arrays, you can combine 2 arrays of same type
val combinedArray = array2 + array

// To check if array is empty

if (array.isEmpty()){

    println("Array is empty")
}

// To check if array contains a particular element

if (array.contains(2)){

    println("Array contains is 1")
}
println(mixedarray[0])

Arraly lists are mutable, you can add and remove elements from it.

val arrayList = arrayListOf("A","B","C")
val arrayList2 = arrayListOf("D","E","F")
// Combine array lists
println(arrayList + arrayList2)

// arraylist is mutable using the add method
val added = arrayList.add("T")
if (added){
    println("Added")
}else{
    println("Add failed")
}

// Add at a particular index. If there is no index, outof bound exception occurs
arrayList.add(2, "T")


// Remove element
val removed = arrayList.remove("A") //Boolean response

if (removed){
    println("removed")
}else{
    println("remove failed")
}

// Get a sublist from an array list, provide start index and end index (end index value wont be taken)
val sublist = arrayList.subList(1,2)

With for loop you can loop through collections, do operations on a list of values etc.

var total = 0
// Loop numbers 1 to 5, find their sum
for (i in 1..5){

    println(i)
    total = total + i
}
println(total)

//loop through collections

val collectionlist = listOf("A","B","C")

for (item in collectionlist){

    println(item)
}
// Similar to SWift 3.0 enumerated() method
for ((index, item) in collectionlist.withIndex()){

    println("Item at $index is $item")
}
 for (i in myArray.indices){

        println(myArray[i])
    }

While A while loop statement in Kotlin programming language repeatedly executes a target statement as long as a given condition is true.

 var index = 10
while (index < 20) {
    println( "Value of index is $index")
    index = index + 1
}

Break :- To Break out of the entire loop

Continue :- Skip a particular iteration

Naming loops Helpful in the case of nested loops, you can specify which loop to break and which loop to continue etc

outer@ for (i in 1..100) {
   for (j in 1..100) {
       if (...) break@outer
   }
}

Below is the simple syntax for function in Kotlin

//fun <functionName>(<parameter>:<dataType>):<return datatype>{
//    return <return value>
//}

// Simple function

fun hellokotlin(){

    println("Hello kotlin")
}

// Function with parameters

fun sayHelloTo(name: String){

    println("Hello" + name)
}

// Function accepts parameters and returns String

fun contructStringFrom(firstName:String, lastName:String):String{

    return firstName + lastName
}

Basic syntax of a class is as follows.

class <ClassName>(Parameters for construction) { 
}

By default a class is closed, to inherit from a class, it need to be defined as open

open class <ClassName>(Parameters for construction): ParentClass { 
}

For overriding properties of the parent class, the properties also need to be defined as open in the Parent class


open class Vehicle(open val color:String,open var numberOfWheels:Int){

}

class Car(override val color: String, override var numberOfWheels: Int):Vehicle(color, numberOfWheels){

}

class Bike(override val color: String, override var numberOfWheels: Int):Vehicle(color, numberOfWheels){

}

Sealed class is a class that can be subclassed only with in the same file. Compiler will be able to do extra checks on all the subclasses and will be able to know all the information about classes and subclasses at compile time

Abstract classes are used when we want to restrict the users from creating an instance of a class, in the above example we wont end up a scenario of creating a Vehicle object, its going to be only Car or bike or may be buses later.

Abstract classes are implictly open

Abstract methods are used when there is different implementation of the parent class method in the child class, so in the parent class only the declaration will be made and the child classes should implement the method.


abstract class Vehicle(open val color:String,open var numberOfWheels:Int){

    abstract fun startEngine()
}

class Car(override val color: String, override var numberOfWheels: Int):Vehicle(color, numberOfWheels){
    override fun startEngine() {
    }


}

class Bike(override val color: String, override var numberOfWheels: Int):Vehicle(color, numberOfWheels){
    override fun startEngine() {
        
    }

}

Interface defines a contract which the adhering classes should implement, its like protocols in Swift. Interfaces can be extended also like protocol extensions, they can contain abstract methods as well as method implementations. Properties can be declared in Interface but they need to abstact or can provide implementation for accessors. Interfaces cannot store state


interface Movable{

     fun startEngine()
}

class Car( val color: String, var numberOfWheels: Int):Movable{
    override fun startEngine() {
    }


}
class Bike( val color: String, var numberOfWheels: Int):Movable{
    override fun startEngine() {
    }

}

Enumerator

Use enum keyword.

enum class State{

    STARTED, FAILED,SUCCESS
}

Usage

if(State.STARTED){
}

Generics

If you have a common functionality which need to handle multiple data types, we use generics.

class Collection<E>{

    fun addElement(){

    }

    fun removeElement(){

    }

}

Extensions are used to add a new behavior to a class eventhough we donot have access to the class's source code, it is similar to extensions in Swift. Extensions can be properties also.

Set doesnt accept duplicate values....set add unique values.
    val myCustomSet = HashSet<String>()

    myCustomSet.add("Hello")
    myCustomSet.add("Hello")

    println(myCustomSet.size)

Maps are similar to dictionaries in Swift. You can have key value pairs

    val mymap = emptyMap<String,String>() // empty readonly map
    val anothermymap = mapOf<String, String>() // another empty readonly map
    val contentMap = mapOf("Don" to "First Name","Bosco" to "LastName")// Read only
    val mutableMap = mutableMapOf("First Name" to "Don" ,"LastName" to "Bosco")
    mutableMap.put("name","Batista")
    mutableMap.filter { it.value == "Don" }
    
    //Looping through a map
    
    for ((key, value) in map) { println("$key -> $value")
    }

Others

Execute an expression if not null

val value = ...
value?.let {
... // execute this block if not null
}

    fun nullableTest(){

    var str:String? = null

    //str = "David"

    val hello = str?.let { sayHello(it) }?: "Undefined"

    Log.i("Kotlin",hello)

}

fun sayHello(name: String): String{

    return "Hello $name"
}
      fun loadNewActivity(view: View){
        val intent = Intent(this, NewActivity::class.java)
        //
        intent.putExtra(...)
    }

......more to come

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment