As we continue, we begin by describing a feature of Kotlin objects called companion objects. We’ll also introduce introduce one new piece of object syntax.
But first, let’s warm up with another graded debugging challenge!
Create a method countLetters
.
countLetters
accepts an array of String
s and returns a Map
from String
s to Int
s.
The map should contain counts of the passed Strings
based on their first letter.
For example, provided the array {"test", "me", "testing"} your Map
should be {"t": 2, "m": 1}.
You should ignore empty String
s and not include any zero counts.
As a reminder, you can retrieve the first character of a String
as a char
using index notation: example[0]
.
You may find substring
more helpful.
You may also want to utilize the Elvis operator ?:
for retrieving a default value from a map when the requested
key does not exist.
this
this
this
is a keyword in Kotlin that you can use in your instance methods.
It always refers to the current instance that is executing the method.
So this:
is equivalent to this:
The example above is one use of this
.
However, we’ll usually just go the first route, and choose parameter names that don’t conflict with our instance variable names.
This helps avoid mistakes.
However, there is one place where we do and will use this
.
Let’s go through it together:
Up until now the properties and methods that we’ve been establishing on our Kotlin objects are instance properties and methods. Meaning each instance of an class has its own:
Even though they share an implementation of doubleName
, instances each act like they have their own doubleName
method.
However, Kotlin also allows us to create methods that are provided by the class and can be accessed without an instance. We do this using something called a companion object. Let’s see how:
Companion object methods cannot access instance variables. Let’s look at why, and the differences between class and instance methods:
In Kotlin, we can create methods that are not associated with any class, simply by declaring them outside a class body:
This works completely fine, and limits the degree to which we need to use companion objects. So if you have a method that doesn’t need an instance, you can either declare it outside the class or in a companion object.
Create a class named Math
. Math
should declare a companion object with a method named add
.
add
should accept two Int
arguments and return their sum.
Companion objects can also declare fields, just like instances:
This can be a good place to put constant values, as shown above, particularly if, like a method, they really belong with the class that defines the companion object.
You can also define non-constant (i.e., var
) properties on companion objects.
However.
This is extremely rare, and very easy to get wrong.
So much so that we won’t bother demonstrating how to do it!
Define a class named Toggler
with a single instance method named toggle
that takes no parameters
and returns a Boolean
.
Toggler
should also provide a primary constructor that accepts a Boolean
argument and sets the initial
state of
the Toggler
instance.
Toggler
maintains one piece of private state: the Boolean
.
Calling toggle
changes the Boolean
from true
to false
or false
to true
and returns the new (not the
old) state of the Boolean
.
So, for example:
Note that the internal state should be private.
Define a public class named Stepper
with a single instance method named next
that takes no parameters
and returns an Int
.
Called multiple times, next
returns a sequence of values separated by a step amount provided to the
primary constructor.
Stepper
should also provide a primary constructor that accepts a Int
argument and sets the step amount.
Stepper
maintains two pieces of private state: the step amount, and the current value, which always starts at 0.
The step amount is passed to the constructor, and should be part of your primary constructor declaration.
But the current value should be declared separately.
Calling next
increments the current value by the step amount, but returns the previous value.
So, for example:
Note that the internal state should be private.
Need more practice? Head over to the practice page.