Programming Kotlin Applications. Бретт Мак-Лахлин
joker = 'j'
A character should be enclosed in a set of single quotes. You can also enclose special characters in quotes and precede the character code with a backslash. For instance, tab is \t
, a line feed is \n
, and a backslash is itself \\
:
val special = '\n'
NOTE Backslash is weird because it is itself an escape character. To get an actual backslash, you use the escape character ( \
) and then another backslash ( \
), which gets you \\
.
For sequences of characters, you likely want a String
. You can create a string with text enclosed in double quotes:
val letters = "abcde"
Simple enough! But note that a single letter in double quotes is a String
, while a single letter in single quotes is a Char
:
val letter = "a" val notStringy = 'a'
Truth or Fiction
For true or false values, you can use a Boolean
. You can assign to a Boolean
either true or false:
val truthful = true val notTrue = false
However, you cannot use 0 or 1 as you can in some languages. A 0 is an Int
(or a Long
, or even a Float
):
val notBoolean = 0 val zeroInt = 0 val zeroLong = 0L val zeroFloat = 0F
A 0 is never a Boolean
, though.
Types Aren't Interchangeable (Part 1)
Most of these types are likely unsurprising. They're typical for most languages. What will surprise you a bit is how far Kotlin will go to ensure you don't get your types wrong. Remember, Kotlin is strongly typed, and the language takes that pretty seriously.
To see this in action, let's add some basic information to the Person
class. Listing 2.3 shows a slightly modified version of this class with some more properties and types.
LISTING 2.3: Person with extra properties
package org.wiley.kotlin.person class Person(var firstName: String, var lastName: String) { var fullName: String var height: Float var age: Int var hasPartner: Boolean // Set the full name when creating an instance init { fullName = "$firstName $lastName" } override fun toString(): String { return fullName } }
You'll notice that each of these new properties has a type: String
or Float
or Int
. Simple enough.
Now, there are some interesting things about the types of these variables, but before getting to that, there's actually a new problem in Person
(in addition to that last name thing that still needs to be dealt with).
You Must Initialize Your Properties
Kotlin requires that you initialize your properties. If you try to compile the Person
class in Listing 2.2, you're going to get an error like this:
Error:(6, 5) Kotlin: Property must be initialized or be abstract
Let's leave the abstract piece of that for later. The easiest fix is to update the Person
constructor to require all of this information. That's pretty straightforward:
class Person(var firstName: String, var lastName: String, var height: Float, var age: Int, var hasPartner: Boolean) { var fullName: String // Set the full name when creating an instance init { fullName = "$firstName $lastName" } // other methods follow }
Now you have to pass in these properties, so they'll pass compilation. Also note that by putting them in the constructor, you don't have to declare them within the class body.
NOTE You can also create additional versions of a Person
constructor if you want to only take in parts of this information on instance creation. We'll come back to that topic in more detail in Chapter 4.
Alternatively, you could assign these properties values in the init
method, as you did with fullName
. However, there's no real way to come up with values for height, age, or whether the person has a partner without taking in input, so this is the more sensible approach.
Now you're ready to go back to main
and do some type-related work.
Types Aren't Interchangeable (Part 2)
First, take a look at PersonApp
, and specifically your main
function. Most IDEs will see that you've updated the constructor and give you some visual cues as to what properties you're currently passing into Person
. Note in Figure 2.4 that IntelliJ has identified the firstName
and lastName
properties being passed in so far.
FIGURE 2.4 IDEs will help you keep constructor properties straight.
Go ahead and make the changes to your function to pass in some values to fill out the new constructor for Person
. You'll need to add a height (I chose to use inches, but any unit of measurement works fine), an age, and whether the person has a partner. Listing 2.4 shows the result.
LISTING 2.4: Filling out your Person instances
import org.wiley.kotlin.person.Person fun main() { // Create a new person val brian = Person("Brian", "Truesby", 68.2, 33, true) println(brian) // Create another person val rose = Person("Rose", "Bushnell", 56.8, 32, true) println(rose) // Change Rose's last name rose.lastName = "Bushnell-Truesby" println(rose) }
Your results are likely not what you expected. You probably got a couple of errors like this:
Error:(5, 44) Kotlin: The floating-point literal does not conform to the expected type Float Error:(9, 43) Kotlin: The floating-point literal does not conform to the expected type Float
What in the world does this mean? If you find the line (the first number in the parentheses) and the place on that line (position 44), you'll see that the error occurs here:
val brian = Person("Brian", "Truesby", 68.2, 33, true)