Название: Programming Kotlin Applications
Автор: Бретт Мак-Лахлин
Издательство: John Wiley & Sons Limited
Жанр: Программы
isbn: 9781119696216
isbn:
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)
You're passing in a decimal for height—in this case 68.2—which seems right. Here's the constructor in Person
:
class Person(var firstName: String, var lastName: String, var height: Float, var age: Int, var hasPartner: Boolean) {
So what gives? The problem is that Kotlin is not converting types. A few things are actually happening here:
1 You give Kotlin the value 68.2. Kotlin sees a decimal number and automatically uses the Double type. This is important! Anytime a decimal is not given an explicit type, Kotlin will use Double.
2 The Double is passed into the Person constructor. However, Person is expecting a Float.
3 Kotlin will not try to convert between these two types—even though, in this case, they are compatible! Instead, Kotlin insists on strong typing, and throws an error.
You Can Explicitly Tell Kotlin What Type to Use
You have two ways to fix this. The easiest is to tell Kotlin that you want the value you're passing in to be treated as a Float
; you can do that by putting a capital F
after the number:
val brian = Person("Brian", "Truesby", 68.2F, 33, true) println(brian) // Create another person val rose = Person("Rose", "Bushnell", 56.8F, 32, true) println(rose)
In this case, you're sending Person
what it wants: a Float
. That passes the type checking and things are OK again.
Try to Anticipate How Types СКАЧАТЬ