The Kotlin Journey — The Awakening
Like many new languages, there is always the hype part, where we hear a lot of news and read lots of articles about how great the language is. There is even a term for such stuff — Hype Driven Development (HDD) (I didn’t coin this term by the way). So Kotlin first appeared in 2011 (The name comes from Kotlin Island, near St. Petersburg and it was developed by Jetbrains). Heard of it some time ago but never gave it any attention. So when Google announced at Google I/0 2017 that it would have first-class support on Android, I knew I had to learn it. After the announcement, the hype started. I read several Medium articles on Kotlin, it was just everywhere. So I tried it, not once, not twice, not thrice, I don’t even remember the count anymore. I just have one word for it — Awesome.
I recently migrated an app I am working on from Java to Kotlin. There was nothing wrong with the Java version but there was so much in Kotlin that would make my work way easier. Over the next few articles I would share my journey from Java to Kotlin. I would like to go through each of the phases of the migration.
Like any normal app, these were the things being done
- General Stuff (Class declarations, functions…all the normal stuff)
- Storing information in SQLite Db (I switched to RoomDb, also made use of LiveData)
- Network Calls with OkHttp and Retrofit
- Display of data on Recycler views
Well I probably did more, but these are the ones I would like to talk about.
General Stuff
So Kotlin makes everyday things great. In Java , definition of a POJO is “hmmmmm”
class User {
private String id, name, email;
public User(String id, String name, String email) {
this.id = id;
this.name = name;
this.email = email;
}
public String getId() {
return this.id;
}
public String getName() {
return this.name;
}
public String getEmail() {
return this.email;
}
}
Well there is nothing wrong about this, its cool till you find out how the Kotlin squad do it
data class User(
val id:String,
val name:String,
val email:String
)
You can define variables using var or val . But note that you cannot reassign a variable declared with val
//var name:Type = Valuevar name:String = "Kwaku"//kotlin has type inference so you don't always have to state the //typevar name = "Bill"//Kotlin would know that name is a String
This does the same thing and more. You could have just used “class” instead of “data class” but data class generates a lot of stuff like equals, hashcode, toString for you behind the scenes. The val means you cant change the values. So lets say you want to make id accessible to only members of the class. Well thats just
data class User(
private val id:String,
val name:String,
val email:String
)
And say you want to set default values, it could not be more natural than this
data class User(
private val id: String = "user0",
val name: String = "Kwaku",
val email: String = "kwaku@gmail.com"
)
Kwaku is a Ghanaian name from the Fante tribe (its given to boys who are born on Wednesday)
What if you had do some iteration on a set of users
void doSomethingOnUserList(List<User> users) {
for (User user : users) {
//do something with user
}
}
The Kotlin squad do this
fun doSomethingOnUserList(users:List<User>){
for(user in users){
//do something with user
}
}
What if you had a map, well in Java you would have something like this
void doSomethingOnUserList(Map<String,User> users) {
for (Map.Entry<String, User> entry : users.entrySet()) {
entry.getKey();
entry.getValue();
}
}
In Kotlin..
fun doSomethingOnUserList(users: Map<String, User>) {
for (user in users) {
//do something with user
user.key
user.value
}
}
I think the comparisons are ok, lets go full Kotlin
Higher Order Functions & Lambda Expressions
In Kotlin, Functions are First-Class Citizens
In programming language design, a first-class citizen (also type, object, entity, or value) in a given programming language is an entity which supports all the operations generally available to other entities. These operations typically include being passed as an argument, returned from a function, modified, and assigned to a variable. -https://en.wikipedia.org/wiki/First-class_citizen
Functions that takes in function(s) as arguments are known as Higher Order Functions.
A lambda expression is basically an un-named function or a function without an identifier (Its originates from Lambda Calculus in mathematics https://en.wikipedia.org/wiki/Lambda_calculus#Definition)
So a Lambda is defined easily as
val addition: (x: Int, y: Int) -> Int = { x, y ->
x + y
}val division: (x: Int, y: Int) -> Int = { x, y ->
if(y==0){
0
}else{
x/y
}
}//call it easilly
val a = addition(2,3)
val b = division(2,3)
Lets go a step furthur
fun binaryOperate(a: Int, b: Int, binaryOperation: (x: Int, y: Int) -> Int):Int {
return binaryOperation(a,b)
}//so we can pass our addition function to our binary operatorbinaryOperate(a=2,b=3, binaryOperation = addition)
binaryOperate(a=8,b=2, binaryOperation = division)
Don’t worry about the a and the b (Kotlin has something called name parameters, this allows me to call functions with arguments in any order)
binaryOperate(binaryOperation = addition, a = 2, b = 3)
This would still work
So lets say I have not defined multiplication and I want to call my binaryOperate with a multiplication body…well thats simple too
binaryOperate(a = 2, b = 3) {x,y->
x*y
}
In Kotlin if your last argument happens to be a lambda you can bring the curly brackets{} out of the parenthesis (). You can also keep it in.
Mind you the last line of the lambda is the return value.
Well there are a ton of things I would have loved to write about, but this article would have been too long.
Things I would have loved to write about
- Generics
- Inline Functions and Reified Types
- Extension functions and properties
- And the cool stuff I cant remember right now
Will see you in the next one.
Thank you for making it this far, all comments are welcome. Y3 be Hyia biom (Twi for we will meet again)
-Twi is a Ghanaian Language