Programming Kotlin Applications. Бретт Мак-Лахлин

Чтение книги онлайн.

Читать онлайн книгу Programming Kotlin Applications - Бретт Мак-Лахлин страница 21

Programming Kotlin Applications - Бретт Мак-Лахлин

Скачать книгу

Person(firstName: String, lastName: String, height: Double, age: Int, hasPartner: Boolean) { var fullName: String var firstName: String var lastName: String var height: Double var age: Int var hasPartner: Boolean // Set the full name when creating an instance init { fullName = "$firstName $lastName" }

      Compile, run, and you'll get another error you've seen before, but this time with all of your properties:

      Error:(6, 5) Kotlin: Property must be initialized or be abstract Error:(7, 5) Kotlin: Property must be initialized or be abstract Error:(8, 5) Kotlin: Property must be initialized or be abstract Error:(9, 5) Kotlin: Property must be initialized or be abstract Error:(10, 5) Kotlin: Property must be initialized or be abstract

      NOTE If that sentence seemed confusing, you're in good company. Two firstName pieces of information are floating around here: the one passed into the constructor, and the property name. That's a problem we'll fix shortly.

      package org.wiley.kotlin.person class Person(firstName: String, lastName: String, height: Double, age: Int, hasPartner: Boolean) { var fullName: String var firstName: String = firstName var lastName: String = lastName var height: Double = height var age: Int = age var hasPartner: Boolean = hasPartner // Set the full name when creating an instance init { fullName = "$firstName $lastName" } override fun toString(): String { return fullName } }

      Take just the line dealing with firstName :

      var firstName: String = firstName

      A property is declared, and it's both read and write, because var is used. (Remember, if you wanted this to be a read-only property, you'd use val.) That property is given a name— firstName—and then a type, String. Then, the new property is assigned a value. In this case, that value is whatever is passed into the constructor through firstName.

      You can now compile your code and run it, and it works again! (Although there's still that last name issue to fix. But you're getting closer.)

      Try to Avoid Overusing Names

      package org.wiley.kotlin.person class Person(_firstName: String, _lastName: String, _height: Double, _age: Int, _hasPartner: Boolean) { var fullName: String var firstName: String = _firstName var lastName: String = _lastName var height: Double = _height var age: Int = _age var hasPartner: Boolean = _hasPartner // Set the full name when creating an instance init { fullName = "$firstName $lastName" } override fun toString(): String { return fullName } }

      NOTE Because Kotlin is so strongly typed and has such unique functionality—multiple constructors, properties versus method inputs, and more—using these coding best practices will really help separate your code from the code of those who are less experienced and savvy.

      Override Mutators for Certain Properties

      You're now finally ready to do what we set out to do: override how changing a first name or last name works. First, you need to see how a typical mutator is defined.

      Here's some more rather Kotlin-specific code that defines a custom mutator; in this case, it's for firstName :

      var firstName: String = _firstName set(value) { field = value }

      WARNING Kotlin uses a property's definition line in a file to determine that, if there's a custom mutator (or accessor), that definition is on the very next line. That's a big deal, and worth noting.

      Then, value represents the value coming into the mutator. So in the following example, value would come to the firstName mutator as “Bobby”:

      // Change Brian's first name brian.firstName = "Bobby"

      Now here's where things look a little odd. There's this line:

      field = value

      What's going on there? What the heck is field ? Well, it's the property being mutated. It's what's called a backing field. So here, field references the backing field for the property, which is firstName (because that's the property just defined). That backing field is assigned the value passed into the mutator—in our example, that's the String “Bobby.”

      The final piece here is understanding why you can't say something like this:

      var firstName: String = _firstName set(value) { firstName = value }

      This will actually compile, but it will give you a horrible error when you try to run and use this class. The problem is that when Kotlin sees this:

      firstName = value

      it interprets that as “run the code that mutates firstName.” But that code is the code already running. So it

Скачать книгу