Monday 12 July 2021

Android Java to Kotlin migration by example part 6: more OOP (static or not static?)

 Let's consider a following, extremely simple, Java code. We're defining a class with one field, one constructor assiging some value to this field and a method, printing a sentence with this field:

Listing 1 (Java simple class)

class Room{
String name;
public Room(String name){
this.name = name;
}

public void describeStatus(){
System.out.println("There is a room called " + name);
}
}

We can now create two instances of this class (rooms), set them some names in constructors and call the describeStatus() method on each. The complete code:

Listing 2 (Java simple class use)

class Room{
String name;
public Room(String name){
this.name = name;
}

public void describeStatus(){
System.out.println("There is a room called " + name);
}
}

public class MainClass {
public static void main(String[] args){
Room roomOne = new Room("living room");
Room kitchen = new Room("kitchen");

roomOne.describeStatus();
kitchen.describeStatus();

}
}

Giving us result:

Listing 3 (result)

There is a room called living room
There is a room called kitchen

Ok, so how to do the same in Kotlin?

First, the class:

Listing 4 (Kotlin simple class)

class Room{
var name: String = ""

constructor(name: String){
this.name = name
}

fun describeStatus(){
println("There is a room called " + name)
}

}

Which can be also defined as:

Listing 4a (Kotlin shorter one-param constructor)

class Room(var name: String) {

fun describeStatus(){
println("There is a room called " + name)
}
}

The constructor is now just a parameter near the class name, defining a parameter in the same time. The code became much shorter!

We use it this way:

Listing 5 (Kotlin simple class use):

package com.mypackage

class Room(var name: String) {

fun describeStatus(){
println("There is a room called " + name)
}
}

fun main() {
val roomOne = Room("living room")
val kitchen = Room("kitchen")

roomOne.describeStatus()
kitchen.describeStatus()
}

Now let's add a static field and a static method to our Java class. As our class represent a room, such static (which means shared between all the class instance) field can store info about whether alarm is active in a room. The static method setAlarm(Boolean active)  shall therefore (dis-)activate the alarm in every room. We'll also change the describeStatus() method to show the status of alarm. Our class code becomes:

Listing 6 (Java static fields and methods definition):

class Room{
String name;
public Room(String name){
this.name = name;
}
    private static Boolean alarmActive = false;
public static void setAlarm(Boolean active){
alarmActive = active;
}

public void describeStatus(){
System.out.println("There is a room called " + name +
", and the alarm is " +
((alarmActive?"on":"off")+" there"));
}
}

...and we can use it in this way:

Listing 7 (Java static fields and methods use):

public class MainClass {
public static void main(String[] args){
Room roomOne = new Room("living room");
Room kitchen = new Room("kitchen");

System.out.println("Before:");
roomOne.describeStatus();
kitchen.describeStatus();

Room.setAlarm(true);

System.out.println("After:");
roomOne.describeStatus();
kitchen.describeStatus();
}
}

Initially, the alarm is false. We're printing the status for all the rooms. Then we call the  setAlarm() method on the class, setting the static field to true. After that, the status in all the rooms becomes "on":

Listing 8 (result):

Before: There is a room called living room, and the alarm is off there There is a room called kitchen, and the alarm is off there After: There is a room called living room, and the alarm is on there There is a room called kitchen, and the alarm is on there

Now... How to achieve this in Kotlin?

Well, in Kotlin there are no "typical" static fields and methods. Instead, there is a mechanism called a companion object, which serves pretty much the same purpose. The fields "shared" between the instances of the class and the method affecting them, should be defined in such object. The Kotlin counterpart of the code from Listing 5 looks like this:

Listing 9 (Kotlin companion object definition):

class Room(var name: String) {

fun describeStatus(){
println(
"There is a room called " + name +
", and the alarm is " +
(if (alarmActive) "on" else "off") + " there")
}
companion object AlarmStatus{
private var alarmActive: Boolean = false

fun setAlarm(active: Boolean){
alarmActive = active
}
}
}

And the use of it is veery similar to the Java static call:

Listing 10 (Kotlin companion object use):

fun main() {
val roomOne = Room("living room")
val kitchen = Room("kitchen")

println("Before:")
roomOne.describeStatus()
kitchen.describeStatus()

Room.setAlarm(true)

println("After:")
roomOne.describeStatus()
kitchen.describeStatus()
}


No comments:

Post a Comment

Python crash course part 10: inheritance and polymorphism

In the last part we've shown how to create and use a class in Python. Today we're going to talk about inheritance: wchich means cre...