Creating Classes

Along with predefined types like IntRange and String, you can also create your own types of objects.

Indeed, creating new types comprises much of the activity in object-oriented programming. You create new types by defining classes.

An object is a piece of the solution for a problem you’re trying to solve. Start by thinking of objects as expressing concepts. As a first approximation, if you discover a “thing” in your problem, represent that thing as an object in your solution. For example, suppose you are creating a program that manages animals in a zoo. Each animal becomes an object in your program.

It makes sense to categorize the different types of animals based on how they behave, their needs, animals they get along with and those they fight with. Everything (that you care about for your solution) different about a species of animal is captured in the classification of that animal’s object. Kotlin uses the class keyword to create new types of objects:

// CreatingClasses/Animals.kt // Create some classes: class Giraffe class Bear class Hippo fun main(args: Array<String>) { // Create some objects: val g1 = Giraffe() val g2 = Giraffe() val b = Bear() val h = Hippo() // Each object() is unique: println(g1) println(g2) println(h) println(b) } /* Sample output: Giraffe@28d93b30 Giraffe@1b6d3586 Hippo@4554617c Bear@74a14482 */

To define a class, start with the class keyword, followed by an identifier for your new class. The class name must begin with a letter (A-Z, upper or lower case), but can include things like numbers and underscores. Following convention, we capitalize the first letter of a class name, and lowercase the first letter of all vals and vars.

Animals.kt starts by defining three new classes, then creates four objects (also called instances) of those classes.

Giraffe is a class, but a particular five-year-old male giraffe that lives in Arizona is an object. When you create a new object, it’s different from all the others, so we give them names like g1 and g2. You see their uniqueness in the rather cryptic output of the last four lines.

The part before the @ is the class name, and the number is the address where the object is located in your computer’s memory. Yes, that’s a number even though it includes some letters—it’s called “hexadecimal notation” and it’s explained in Wikipedia.

The classes defined here (Giraffe, Bear, and Hippo) are as simple as possible: the entire class definition is a single line. More complex classes use curly braces ({ and }) to describe the characteristics and behaviors for that class. The code inside the curly braces is the class body.

A function defined within a class belongs to that class. In Kotlin, such function is called a member function of the class. Some object-oriented languages like Java choose to call these methods, a term that came from early object-oriented languages like Smalltalk. To emphasize the functional nature of Kotlin, the designers chose to drop the term “method,” as some beginners found the distinction confusing. Instead, the term “function” is used everywhere.

If it is unambiguous, we will just say “function.” If we need to make a distinction, functions that belong to a class are called member functions, while functions that exist by themselves and are not part of a class are called top-level functions.

Here, the bark() function belongs to the Dog class:

// CreatingClasses/Dog.kt class Dog { fun bark() = "yip!" } fun main(args: Array<String>) { val dog = Dog() }

In main(), we create a Dog object and assign it to val dog, but don’t do anything else with that object. The compiler produces a warning about the fact that we don’t use dog.

Member functions are called (invoked) with the object name, followed by a . (dot/period), followed by the function name and argument list. Here we call the meow() function and display the result:

// CreatingClasses/Cat.kt class Cat { fun meow() = "mew!" } fun main(args: Array<String>) { val cat = Cat() // Call 'meow()' for 'cat': val m1 = cat.meow() println(m1) } /* Output: mew! */

Member functions act on particular instances of a class. When you call meow(), you must call it with an object. During the call, meow() can access other members of that object. Kotlin keeps track of the object of interest by quietly passing around a reference to that object. That reference is available as the keyword this.

Member functions have special access to other elements within a class. You can access all the members inside a class either by explicitly using the this keyword, or without using a dot (that is, without qualifying it). Here, exercise() calls speak() via this, and then without qualification:

// CreatingClasses/Hamster.kt class Hamster { fun speak() = "squeak! " fun exercise() = this.speak() + // Qualified with 'this' speak() + // Without 'this' "Running on wheel" } fun main(args: Array<String>) { val hamster = Hamster() println(hamster.exercise()) } /* Output: squeak! squeak! Running on wheel */

In exercise(), the two approaches for calling the speak() member function are equivalent: you can either use an explicit this or omit it.

Sometimes you’ll see code using an explicit this when it doesn’t need to. This often comes from programmers who are used to a different language where this is either required, or part of some style. Using a feature when you don’t need it tends to be confusing for anyone reading that code—they spend time trying to figure out why you’re doing it. We recommend avoiding the unnecessary use of this.

Outside the class, you must say hamster.exercise() and hamster.speak().

Previous          Next

©2018 Mindview LLC. All Rights Reserved.