Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Friday, September 8, 2017

Kotlin cheat sheet

Yet another kotlin cheat sheet.
Enjoy!

Variable declaration
Java:

public class JavaFile {
    String mutableVariable = "Mutable";
    final String finalVariable = "NotMutable";
    private final String privateVariable = "privateNotMutable";
    private String initialNull = null;
}

Kotlin:

class KotlinFile {
    var mutableVariable = "Mutable"
    val finalVariable = "NotMutable"
    private val privateVariable = "privateNotMutable"
    var initialNull: String? = null
}
...and Kotlin also has a couple of new ways. One of them is lateinit var:

class KotlinFile {
    var mutableVariable = "Mutable"
    val finalVariable = "NotMutable"
    private val privateVariable = "privateNotMutable"
    var initialNull: String? = null

    lateinit var somewhatNull: String
    init {
        somewhatNull = "Initialized at a later time"
    }
}


Methods / Functions (in practice they are the same things)
Java:

public class JavaFile {
    private void myVoidMethod(){
        // do something
        // no returns
    }
    
    public String myStringMethod() {
        return "";
    }
    
    public Double calculateArea(final double width, final double length) {
        return width * length;
    }
}

Kotlin:

class KotlinFile {
    private fun myVoidMethod() {
        // do something
        // no returns
    }

    fun myStringMethod(): String {
        return ""
    }

    fun calculateArea(width: Double, length: Double): Double {
        return width * length
    }
}


Static field
Java:

public class JavaFile {
    final static String MY_CONSTANT = "some_value";
    final static String SOME_OTHER_CONSTANT = "some_value_2";

    // called as:
    // JavaFile.MY_CONSTANT
    // JavaFile.SOME_OTHER_CONSTANT
}

Kotlin (note that Kotlin doesn't really have the concept of static, but you can achieve the same result from this):

class KotlinFile {
    companion object {
        val MY_CONSTANT = "some_value"
        val SOME_OTHER_CONSTANT = "some_value_2"
    }

    // called as:
    // KotlinFile.MY_CONSTANT
    // KotlinFile.SOME_OTHER_CONSTANT
}


Constructors
Java

public class JavaFile {
    private String myString;
    private int myNumber;

    public JavaFile(final String myStringParam, final int myNumberParam) {
        myString = myStringParam;
        myNumber = myNumberParam;
    }
    
    public JavaFile(final String myStringParam) {
        myString = myStringParam;
        myNumber = -1;
    }
}

Kotlin:

class KotlinFile(val myString: String, val myNumber: Int) {

    // in Kotlin, this is called a "secondary constructor"
    // the 'this()' is then calling the "primary constructor"
    constructor(myString: String) : this(myString, -1)
}

Kotlin, option 2:

class KotlinFile(val myString: String, val myNumber: Int = -1) {
    // this then overloads the constructor and generates 2 versions
    // one takes a String and an Int
    // the second one is just a String. The Int value is then set to the defined -1
}



Inheritance and Extension

Let's move on to more complex stuff. Let's say we have some java classes we want extend and implement. Here they are:

BaseAnimal.java

public class BaseAnimal {
    private final int mNumberLegs;
    
    public BaseAnimal(final int numberLegs) {
        mNumberLegs = numberLegs;
    }
    
    public int getNumberLegs() {
        return mNumberLegs;
    }
}

JavaInterfaceOne.java

public interface JavaInterfaceOne {
    void makeDrink(final String someFlavor);
}

JavaInterfaceTwo.java

public interface JavaInterfaceTwo {
    void makeSandwich(final String someIngredient);
}

We want to extend the base class, and implement the interface classes. Here's how we do it.

Java:

public class JavaFile extends BaseAnimal implements JavaInterfaceOne, JavaInterfaceTwo {

    public JavaFile() {
        super(4);
    }

    @Override
    public void makeDrink(String someFlavor) {
        // do something
    }

    @Override
    public void makeSandwich(String someIngredient) {
        // do something
    }
}
In case there's any doubt, we extend the BaseAnimal class. Because of this we need to have a constructor and invoke the super constructor with some integer for the number of legs.
The other 2 methods are because we're implementing 2 other classes, and each class requires to override each of their methods.

Now, here's how we do it using Kotlin:

class KotlinFile: BaseAnimal(4), JavaInterfaceOne, JavaInterfaceTwo {
    override fun makeDrink(someFlavor: String?) {
        // do something
    }

    override fun makeSandwich(someIngredient: String?) {
        // do something
    }
}
A few notable differences:
  • There's no implements or extends keyword anymore
  • We declare that we're going to implement or extend a class by adding a colon ( : ) after our class name. If our class has a constructor, then its class ClassName() : SomeInterface
  • We use parenthesis (technically a constructor) for classes we extend
  • We don't use parenthesis for classes we implement
  • If we need to call a super for the base class, we pass that in the constructor of the class we're extending (notice the (4) next to BaseAnimal)
  • Android Studio autocompletes the variables inside the Interface methods as conditionals (with the question mark ? ). I'm currently not sure why, of it is better to have it.

At this point, this will work. This will work as a Java class, and as a Kotlin class.
Why would I even mention this??

There's an interesting difference with Kotlin regarding extending a class...
Let's say we create our Base class in Kotlin instead:

class BaseAnimalKotlin(val numberLegs: Int)

And now let's modify our Kotlin class to extend this new Kotlin version of the Base class:

class KotlinFile: BaseAnimalKotlin(4), JavaInterfaceOne, JavaInterfaceTwo {
    override fun makeDrink(someFlavor: String) {
        // do something
    }

    override fun makeSandwich(someIngredient: String) {
        // do something
    }
}
This will, unfortunately, not even compile. The error is: "This type is final, so it cannot be inherited from"
What is this???

In Kotlin, if you want a class to be extended you must "allow" so by making the base class open.
This means that the fix is on our Base class, to be this:

open class BaseAnimalKotlin(val numberLegs: Int)
Notice how the first word in this line is the keyword open. This means our Base class is "open" for extension.
I personally do not like this, but that's just my opinion...