Название: Programming Kotlin Applications
Автор: Бретт Мак-Лахлин
Издательство: John Wiley & Sons Limited
Жанр: Программы
isbn: 9781119696216
isbn:
FIGURE 1.10 Why doesn't this override of toString() work?
What gives here? Well, it turns out to be a little tricky.
All Data Is Not a Property Value
You have a constructor and it takes in two pieces of data: firstName
and lastName
. That's controlled by the constructor declaration:
class Person(firstName: String, lastName: String) {
But here's what is tricky: just accepting those values does not actually turn them into property values. That's why you get the error in Figure 1.10; your Person
object accepted a first and last name, but then promptly ignored them. They aren't available to be used in your toString()
overridden method.
You need to use the val
keyword in front of each piece of data to turn that data into property values. Here's the change you need to make:
class Person(val firstName: String, val lastName: String) {
Specifically, by using val
(or var
, which we'll talk about shortly), you've created variables, and assigned them to the Person
instance being created. That then allows those variables (or properties, to be even more precise) to be accessed, like in your toString()
method.
Make these changes (see Listing 1.5 to make sure you're caught up) and then compile and run your program.
LISTING 1.5: Converting data to actual properties
class Person(val firstName: String, val lastName: String) { override fun toString(): String { return "$firstName $lastName" } } fun main() { val brian = Person("Brian", "Truesby") println(brian) }
You should get a single line of output:
Brian Truesby
Obviously, the name will be different if you passed in different values for first and last name, but the result is the same, and it's a big deal. You've now:
Created a new object
Defined a constructor for the object
Accepted two pieces of data in that constructor and stored them as properties associated with the object instance
Overridden a method and made it useful
Written a main function
Instantiated your custom object and passed in values
Used the object to print itself out, using your overridden method
Not too bad for getting started! There's just one more detail to work through before closing shop on your first foray into Kotlin.
INITIALIZE AN OBJECT AND CHANGE A VARIABLE
Suppose you want to play around a bit with your Person
class. Try this out: update your code to match Listing 1.6 (some of this may be confusing, but you can probably figure out most of what's going on).
LISTING 1.6: Creating a new property for a Person
class Person(val firstName: String, val lastName: String) { val fullName: String // Set the full name when creating an instance init { fullName = "$firstName $lastName" } override fun toString(): String { return fullName } } fun main() { // Create a new person val brian = Person("Brian", "Truesby") // Create another person val rose = Person("Rose", "Bushnell") println(brian) }
You'll see a number of new things here, but none are too surprising. First, a new variable is declared inside the Person
object: fullName
. This is something you've already done in your main
function. This time, though, because you're doing it inside the Person
object, it automatically becomes part of each Person
instance.
Another small change is the addition of a new Person
instance in main
; this time it's a variable named rose
.
Then, there's a new keyword: init
. That bears further discussion.
Initialize a Class with a Block
In most programming languages, Java included, a constructor takes in values (as it does in your Person
class) and perhaps does some basic logic. Kotlin does this a bit differently; it introduces the idea of an initializer block. It's this block—identified conveniently with the init
keyword—where you put code that should run every time an object is created.
This is a bit different than you may be used to: data comes in through a constructor, but it's separated from the initialization code, which is in the initializer block.
In this case, the initializer block uses the new fullName
variable and sets it using the first and last name properties passed in through the class constructor:
// Set the full name when creating an instance init { fullName = "$firstName $lastName" } Then this new variable is used in toString(): override fun toString(): String { return fullName }
WARNING As much new material as this chapter introduces, you may have just run across the most important thing that you may learn, in the long-term sense. By changing toString()
to use fullName
, rather than also using the firstName
and lastName
variables directly, you are implementing a principle called DRY: Don't Repeat Yourself.
In this case, you're not repeating the combination of first name and last name, which was done already in the initializer block. You assign that combination to a variable, and then forever more, you should use that variable instead of what it actually references. More on this later, but take note here: this is a big deal!
Kotlin Auto-Generates Getters and Setters
At this point, things are going well. Part of that is all СКАЧАТЬ