Lesson 2 - First object-oriented app in Kotlin - Hello object world

Kotlin OOP 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 :)

New package in Kotlin

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).

New file in Kotlin

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.

New class in Kotlin

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.

Name of the new class in Kotlin

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:

Quick information lookup in IntelliJ

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! ;-)


 

 

Article has been written for you by Samuel Kodytek
Avatar
Do you like this article?
No one has rated this quite yet, be the first one!
Activities (4)

 

 

Comments

To maintain the quality of discussion, we only allow registered members to comment. Sign in. If you're new, Sign up, it's free.

No one has commented yet - be the first!