Hello, Hi.
My name is Artur and welcome to my first episode about Kotlin.
Today, I will show you basic parts of this language.
As you may know, Kotlin was created by JetBrains.
This language can be used not only to Android development, but first
we need to know how to use this language to anything.
In this tutorial, I will be using IntelliJ which was created by JetBrains, too, so it works great with Kotlin.
Ok, let's create a project. After opening IntelliJ, you can choose "Create New project".
You can notice Kotlin to the left and click it and there is Kotlin and JVM.
As you can see, Kotlin can compile either to JS code, not only to Java bytecode.
I will not discuss it there but I encourage you to check it.
You can click next and project name...
it doesn't matter but I will type "Kotlin-01" and SDK Java 1.9, Kotlin Java Runtime...
Everything is ok, so let's click finish.
Oops, not this window, sorry...
Project was generated by IntelliJ.
For now, there is a simple structure. We have there simple Kotlin folder, root folder and above is source folder.
By typing "Alt + Insert" in IntelliJ, we can generate package, just like in Java.
Let's say that package will be pl.simplecoding.kotlin.basics
Ok, simple package was generated.
By typing "Alt + Insert", we can create another file. It would be "val-var".
"Val" will be from values and "var" will be from variables.
There are variables and values in Kotlin but I will say something about it soon.
File in Kotlin has an extension "kt". Ok, in IntelliJ we can type "main".
By clicking "tab", main function will be generated.
What do we have here?
There is main function which is preceded by "fun" keyword and in Kotlin we have to type it.
To this main function args are passed which are array of strings, like in Java.
But there arrays is a generic class which receives, in this case, strings.
Also, you can see that there is no class.
You can just type function and it's okay in Kotlin. You don't have to use classes.
We'll print "Hello, Kotlin".
As you can see there is print function, which is something like "System.out.print" in Java.
Behind the scenes, this function is called but in this case we can just type in this way.
Also, semicolon is not needed in Kotlin. We don't have to use it.
By clicking "K" icon in IntelliJ we can just run this program.
Okay, let's see.
As you can see, there is simple "Hello, Kotlin" in our console displayed.
Ok, let's, declare first variable. To do it, we need to type "var" or "val" at first.
"Var" means variable and it can be changed. Let's type "var mutable = 1".
I don't define type explicitly. if Kotlin is able to recognize what is there, you don't have to type it.
It's optional.
Ok, this variable can be easily changed, so let's type "mutable = 2".
Ok, what if you want to type let's "mutable = "hello"".
It's string. Program will not compile. Kotlin will know that it's not allowed here.
Okay but what about null?
You may think "it shouldn't be a problem". Fortunately, as you can see "mutable = null" will not compile.
Why? Kotlin is null-safety. What does it mean?
It means that if you don't declare explicitly that this variable is nullable, assigning null to it won't be possible. Just like there.
Ok, but how to declare variable as nullable?
it's easy but first I will print everything out to show that it's okay.
Ok, and run it. Let's see.
There is "Hello, Kotlin", 1 and 2, great.
Okay let's create a nullable variable for now.
There will be "var nullable". Variable type can be declared after colon sign.
Let's create "Any?".
It means that this variable is of type "Any", which is something like "Object" in Java.
As you can see right there, root class, super class.
Question mark means that it might be in null, that's all.
Also, if type is declared explicitly, you don't have to initialize variable at first. You can do it later.
Let's declare "nullable = 1.0".
Ok, it's "Any", so string should be okay there but we print it either.
Ok, so let's type "nullable = "nullable""
It's okay for now, there is no problem.
Let's print it out too and another one, let's say "nullable = null".
Wow, there is no problem either. Let's see what print will return to us.
Let's run program again.
You can see there is everything okay 1, 2, 1.0, "nullable" string and null.
As you can see, everything has been printed, null either.
I think that you understand now how variables works in Kotlin.
Let's go to the values.
As I said earlier, value cannot be changed.
It's like "final" declaration in Java.
Let's type "val immutable = 3"
I will print it again.
Ok let's try to change it, let's type "immutable = 5".
We cannot do it. Val cannot be reassigned.
Ok, what about value initialization?
It's like with variables.
If you define type explicity, you can do it later. Otherwise you would do it at first.
It will work but IntelliJ prefer to joined assignment as, let's say, "nullable = 5.0" above.
One more print to see what is with that "immutable".
Ok, 3 has been printed, great.
That's all for now about values and variables.
Let's talk about classes in Kotlin for a moment.
You don't need them but, of course, they exist and you will create a new class there.
Let's create class "PhoneContact".
It will store simple information about contact in our book.
Class can be declared by typing "class" keyword and after that class name.
We want to create something like simple Java POJO.
You would probably create or generate setters, getters, constructors, toString, equals, blah, blah, blah, lots of boilerplate.
In Kotlin, you just need to preceed class by "data" keyword. That's all.
Let's do it. Type "data".
See?
Condition is that we need to declare at least one class' field. How to do it?
Parameter must be preceded by "val" or "var" keyword in constructor.
You know what it means now. We need first name, which will be string and will be a value.
We cannot change it. Another parameter will be last name. Like first name, string and cannot be changed.
Also, we need phone number.
Let's say just number and it will be string.
It is not nullable but it can be changed.
Almost like a NUMBER. Difference is that country can be null.
Let's type question mark at the end. Ok, that's all.
Class doesn't even have a body.
Beautiful, isn't it?
Curly braces are redundant, you don't need them.
Class as that is great.
Ok, let's use this class.
Let's create another file in program.
Kotlin file, let's say it will be "phoneprogram.kt".
As usual, we need declare main function, as earlier.
Let's create first value and it will be "firstContact".
Object will be created almost like in Java.
Difference is that there is no "new" keyword, so we will not type it.
Constructor may be used as the same as in Java.
We will pass values in the same order, so first name will be "Artur".
Last name "Simplecoding" for example.
Some random number "123123"
Country - "Poland", of course.
Let's create more contacts, ok?
So, another contact will be contact without country.
Let's type "contactWithoutCountry" and of course we need to use constructor.
"PhoneContact" and first name will be "Anna", last name "Bella", ok?
And another random number, but now country can be null.
Unfortunately, it doesn't look well, isn't it?
We shouldn't do it in this way, but
In Kotlin, there's something like default values in constructors.
You can just type something like "= null". It means that if we won't
pass a parameter for country, default value will be null.
Now, we can use two different constructor. See?
One with country and another one without country.
There, country is set as a null and we didn't do that explicitly.
Remember that "val" and "var" for object means that reference can or cannot be changed.
But object fields variable can be changed.
For example, first name is a value so another first name assignment will not work.
"Val cannot be reassigned"
But, we have two fields where we're using variable, for example number.
We can easily change it by typing "number = "111111""
It works like setter in Java. Simple assignment.
Another cool thing about classes is that we can pass values in different order.
Let's create another contact in different order.
To do it, you need to just type a field name, country let's say at first,
equal sign and value, for example "Poland".
Another field, let's say, first name.
Will be "Michael" and last name "Scofield".
Have you watched "Prison Break"? I think you have.
Last, number, because I didn't pass it so let's type another random number.
This constructor is valid.
You can do it every time when you have these fields in constructor.
That's all about classes themselves for now.
I will show you some interesting things in Kotlin collections.
But first, let's create another contact which we'll be using in those collections.
Let's say it will be contact from Congo for example.
"val contactFromCongo = PhoneContact("
We will pass random first name, last name.
Number will be random either. Country is important I will show you later why.
Let's type "Congo".
We have created 4 contacts above.
They can be stored in an array or in a list.
In Java, you would use some static method or just create new list and type "add", "add", "add".
Boring... in Kotlin, we can use "listOf()" function
where arguments are list's contacts.
For other collections like maps or arrays, similar functions exist
Let's add all contacts to this list.
It will be first contact, contact without country.
Contact in diff order and contact from Congo.
The important thing is that those collections are immutable.
Contacts cannot be changed.
If you want list to be mutable, you just need to call almost the same function but with "mutable" prefix.
It's almost the same but syntax is similar.
There is another type - mutable list with phone contacts.
In this case, we will stay with immutable version.
It's perfectly okay for now.
As you may know, functional programming is very popular these days.
In Java, stream API is available since version 8.
Kotlin, although can compile to Java 6 bytecode, allows us to use syntax typical for functional programming.
You can create lambdas, pass functions as arguments or even store functions in variables.
But maybe step-by-step.
Let's start with printing first name and last name for each contact where each contact will be string.
First name, space, last name.
For example: "Artur Simplecoding".
We'll use "map" function for that.
Let's type "contacts" and we'll map each contact.
Curly braces notation means that we are passing lambda there.
I hope that you've heard about it.
We will refer to object by "contact" variable.
After arrow, we will type how mapped contact will looks.
It will be string, which will be printed later.
In Java, you would concatenate 2 fields.
We'll type "contact.firstName" + " " + "contact.lastName"
In Kotlin, you can use interpolation.
We can refer to fields or even call functions in string.
There, we will pass first name, space, last name.
It's ok. It will be almost the same.
If you want to refer to a variable you don't have to type these curly braces.
$contact is ok.
Great, this will be our simple user in this string.
For now, we want to display mapped contacts.
We will use "forEach" function to do that.
I think that you know what it does.
It will calls passed lambda for each mapped contact.
We will refer to mapped contact by "mappedContact".
After arrow sign, I will just print it.
Print this map contact so it is "println(mappedContact").
Ok, I think that is readable and easy to understand, so let's run this program.
Each contact has been displayed as we want it.
But what if we want to display contacts only from Poland?
I am not a racist but you know...international calls are not cheap.
In this case, we can filter these contacts by "filter" function.
It will receive lambda either and it will return only those objects for which passed function will return true.
Let's say that we want to each contact where country is Poland, so we will type "Poland" and "equals", but there is a difference.
I didn't use variable name because you can refer to variable by "it" word if it's only variable in this lambda.
There would be our contact. As you can see, there was each field.
We can set "ignoreCase" as a "true", because "Poland" lower case upper case it doesn't matter for us, so this notation is ok.
We will print each contact but we will do almost as above, in map function but we will use "it" word.
It will be "it.firstName" and "it.lastName".
Let's show where our filtered will start so let's type "println("Filtered contacts")"
Let's run program again.
See? In filtered contact are only "Artur Simplecoding" from Poland and "Michale Scofield" from Poland.
Anna Bella's country was null and ...:) is from Congo, so they weren't displayed.
Ok, last functionality which I want to show you.
You can group contacts, by some key, of course. Other collections too.
Let's say that we want to group contacts by country.
To do that, we need to call "groupBy" function.
Now, in lambda, we can pass a field which should be returned as a key.
We will refer to, of course, country.
We can call some function there, but we will just refer to country without changing anything.
We will assign it to "grouppedContacts" value.
As you can see, there is map where key is the string with question mark, like a country.
And list with PhoneContacts for each key.
Now, we want to, of course, print each group.
Each group has a country as a key and value is a whole list
In this lambda is map, so we will refer separately to key and value by
typing these two things after arrow sign and we will print it.
Let's type this key and interpolate this key by "$key" and after arrow, we will print value.
There will be printed whole list.
See? For key "Poland", we have list with contacts: Artur Simplecoding from country Poland and there is Michael Scofield from Poland.
Another key is "null". As I said earlier, there is no problem, Anna Bella is from "null" country.
And contact from Congo is with key "Congo".
Ok, that's all for now. Thank you for your time!
There will be new videos about Kotlin, so stay tuned, subscribe, and check my blog sometimes (www.simplecoding.pl).
Of course, sources are attached to this video.
Bye!
Không có nhận xét nào:
Đăng nhận xét