Lesson 2 - First object-oriented app in Kotlin - Hello object world
In the previous lesson, Introduction to object-oriented programming in Kotlin, we introduced what object-oriented programming was and went over what makes it more efficient than any other programming methodology. We already know that objects have properties and methods. We also know that to create an object we'd have to create a class first. Remember that a class is a pattern according to which we create instances later.
As we did in the Kotlin basic constructs course we'll create what must always be done when you encounter a new paradigm in programming, a "Hello World" program. A Hello object world program, to be precise!
We'll start by creating a new Kotlin application in IntelliJ as we're used
to. In object-oriented applications, classes are organized in packages.
Therefore, we'll first add a new package
into our application.
Right-click on the src/
folder in our project and select New ->
Package. You can name your package as you like, but they're usually named after
a domain you own (e.g. I'll name it social.ict
, because it's a
package by ict.social). We'll talk about packages more in further lessons

Next, we'll create a file in our new package which will contain our
main()
method (The process is almost the same as in the first
lesson. Except instead of the src/
folder, we'll right-click on our
package).

We'll define the main()
method in our newly created
Main.kt
file as we're used to from the previous lessons.
package social.ict
fun main(args: Array<String>) {
}
Finally, we can create a new class. Right click on our package in the
src/
folder and select New -> Kotlin File/Class.

We'll name the class Greeter
and confirm. Under the title,
select "Class" in the dropdown menu. We name classes using CamelCase, meaning
that the first letter in every word in the class name is capitalized and we
don't write spaces. The name, of course, shouldn't contain any accent
characters, if your native language uses any, you can use them in strings, but
never in identifiers.

We're going to create a "greeter" object using this class later, which will
be able to greet the user. You might've noticed by now that we're treating the
program in a different way, for every action, there is some object responsible.
One should not simply start by writing stuff into the main()
method. In our case, it may seem useless, but in more complex applications it'll
prove to be more than worthwhile
Another .kt
file will be added to our package and IntelliJ will
open it for us. We can later return to the original Main.kt
with
the main()
method using tabs or via the Project menu on the left
side. If we want our new Greeter
class to be visible in the default
file, containing the main()
method, both files must be in the same
package. This condition is met in our application.
Let's take a look at what IntelliJ generated for us and describe the code. Then, we'll add our own greeting method to the class.
package social.ict class Greeter { }
In the package
, there's our class declared by the
class
keyword. The class is named Greeter
and is empty
now.
Next, we'll add a greet() method to the Greeter class, which will be publicly visible and won't return a value or take any parameters.
Method declaration in Kotlin is the following:
[access modifier] [methodName]([paramters]) : [return type]
Before the method, we can specify the access modifier, in our case
public
. The method won't return any value, we'll achieve that by
not specifying any return type. As next, we write the method's name. We name
methods in a similar fashion as variables, using camelCase, but the very first
letter is lowercase. Parentheses with parameters are required, we'll leave them
empty since the method won't have any parameters. In the method body, we'll
write code that prints a message to the console.
Our class will now look like this:
package social.ict class Greeter { fun greet() { println("Hello object world!") } }
If we don't specify the modifier before the method, Kotlin
assumes that the method should be public
, i.e. publicly visible. We
usually omit this modifier in Kotlin.
That's all we'll do for the class for now. Let's move on to
Main.kt
.
We'll create an instance of the Greeter
class
in the main()
method body. Which will be a greeter object that
we'll be able to work with. Objects are stored in variables where the class name
is used as the data type. Instances usually have the same name as classes, but
with the first character in lowercase. Let's declare the variable and then store
a new Greeter
class instance within it:
val greeter = Greeter()
Notice that the Kotlin language doesn't use the new
keyword as we'd use for example in Java.
The first line says: "I want a variable named "greeter" that will contain a Greeter instance". We've already worked with the variables like this.
When a new instance is created, the constructor is called. That's a special method of the class, that's why we write the empty parenthesis when creating a new instance, because we call this "initialization" method. The constructor usually contains some initialization of the object's internal state, e.g. it initializes the properties with default values. We haven't declared a constructor in our class, that's why Kotlin created the implicit parameterless constructor. So creating an instance of an object is similar to calling a method.
Since now we have a Greeter
class instance in a variable, we can
let it greet the user. We'll call the greet()
method as
greeter.greet()
. The main()
method code will now look
like this:
val greeter = Greeter() greeter.greet()
Let's run the program. The output is as follows:
Hello object world!
We've successfully made our first object-oriented app in Kotlin!
Now let's add a name
parameter to our greet()
method, so it could greet the user properly:
fun greet(name: String) {
println("Hi $name")
}
The syntax of the method parameter is the same as the syntax of a variable.
If we wanted more parameters, we'd separate them with commas. Let's modify our
main()
method now:
val greeter = Greeter() greeter.greet("Carl") greeter.greet("Peter")
Our code is now in a method and we're able to call it multiple times with different parameters. We don't have to copy "Hi ..." twice. We'll separate code logically into methods from now.
The output:
Hi Carl Hi Peter
Let's add some property (attribute) to the class, e.g. a text
where the greeting will be stored. Properties are defined as variables as well.
As it was with methods, if we omit the property's modifier, Kotlin assumes that
it's public
. Here's what your class should look like at this
point:
package social.ict class Greeter { var text: String = "" fun greet(name: String) { println("$text $name") } }
We have to initialize the text in the instance created in
Main.kt
:
val greeter = Greeter() greeter.text = "Hi " greeter.greet("Carl") greeter.greet("Peter") greeter.text = "Hello programmer" greeter.greet("Richard")
The output:
Hi Carl Hi Peter Hello programmer Richard
In object-oriented design it is not recommended to let each object control
input and output, i.e. printing lots of stuff into the console. Each object
should have a duty to fulfill and shouldn't overlook its limitations. Let's make
our object solely responsible for the greeting part, we'll print outside the
object, i.e. in the main()
method. The advantage to designing
objects with a single responsibility is that they're then universal and
reusable. The object can only output text to the console now, but we'll change
it so the method will only return the text and it'll be up to the recipient to
know what to do with it. We could also store greetings into files, print them on
websites or process them further.
Since we want the method to return a String
value, we'll set the
String
data type to it. We use the return keyword
to return a value. Return terminates a method and returns a value. Any code in
the method's body after the return
will not be executed! Let's
modify both classes:
The greet()
method in Greeter.kt
:
fun greet(name: String): String { return "$text $name" }
The main()
method body in Main.kt
:
val greeter = Greeter() greeter.text = "Hi " println(greeter.greet("Carl")) println(greeter.greet("Peter")) greeter.text = "Hello programmer" println(greeter.greet("Richard"))
Now, our code follows the guidelines of good OOP and over all programming
practices. We will also add comments in our class accordingly. We'll add
comments over the class name and over the name of each property and method.
We'll use the /** Comment */
syntax. Comments are useful when we
make new class methods because its description will then be available to us in
IntelliJ. A fully documented class might look something like this:
package social.ict /** The class represents a greeter whose purpose is to greet the user */ class Greeter { /** Greeting text */ var text: String = "" /** * Greets the user with the stored greeting and their name * @param name The user's name * @return The greeting text */ fun greet(name: String): String { return "$text $name" } }
/** */
is a multiline comment, the syntax is called Javadoc. If
you describe your classes properly, the programmer documentation can then be
created with just a single click.
Let's check and see if IntelliJ actually displays descriptions we've set in Javadoc:

Great! Our program already has some quality to it, despite it being
relatively useless. If you want, you can try to create an object-oriented remake
of our console calculator. In the next lesson, RollingDie in Kotlin - Constructors and random numbers, we'll program a simple
game, we'll make two objects, warriors, compete in an arena, which will also be
an object). See? Now you have something to look forward to!