Название: Programming Kotlin Applications
Автор: Бретт Мак-Лахлин
Издательство: John Wiley & Sons Limited
Жанр: Программы
isbn: 9781119696216
isbn:
It's doing something else, too: it's auto-generating some extra methods on your class. Because you made firstName
and lastName
property values (with that val
keyword), and you defined a fullName
property, Kotlin created getters and setters for all of those properties.
Terminology Update: Getters, Setters, Mutators, Accessors
A getter is a method that allows you to get a value. For instance, you can add this into your main
function, and it will not only work, but print out just the first name of the brian Person
instance:
// Create a new person val brian = Person("Brian", "Truesby") println(brian.firstName)
This works because you have a getter on Person
for firstName
. You can do the same with fullName
and lastName
, too. This getter is, more formally, an accessor. It provides access to a value, in this case a property of Person
. And it's “free” because Kotlin creates this accessor for you.
Kotlin also gives you a setter, or (again, more formally) a mutator. A mutator lets you mutate a value, which just means to change it. So you can add this into your program:
// Create a new person val brian = Person("Brian", "Truesby") println(brian.firstName) // Create another person val rose = Person("Rose", "Bushnell") rose.lastName = "Bushnell-Truesby"
Just as you can get data through an accessor, you can update data through mutators.
WARNING For the most part, I'll be calling getters accessors, and calling setters mutators. That's not as common as “getter” or “setter,” but as a good friend and editor of mine once told me, a setter is a hairy and somewhat fluffy dog; a mutator lets you update class data. The difference—and his colorful explanation—has stuck with me for 20 years.
Now, if you've gone ahead and compiled this code, you've run into yet another odd error, and that's the last thing to fix before moving on from this initial foray into objects.
Constants Can't Change (Sort of)
Here's the code causing the problem:
// Create another person val rose = Person("Rose", "Bushnell") rose.lastName = "Bushnell-Truesby"
If you try to run this code, you'll get an error like this:
Error: Kotlin: Val cannot be reassigned
One of the things that is fairly unique about Kotlin is its strong stance on variables. Specifically, Kotlin allows you to not just declare the type of a variable, but also whether that variable is a mutable variable, or a constant variable.
NOTE The terminology here is a bit confusing, so take your time. Just as with methods being declared with the fun
keyword, the idea of a constant variable takes a little getting used to.
When you declare a variable in Kotlin, you can use the keyword val
, as you've already done:
val brian = Person("Brian", "Truesby")
But you can also use the keyword var
, something you haven't done yet. That would look like this:
var brian = Person("Brian", "Truesby")
First, in both cases, you end up with a variable; val
does not stand for value, for example, but is simply another way to declare a variable, alongside var
. When you use val
, you are creating a constant variable. In Kotlin, a constant variable can be assigned a value once, and only once. That variable is then constant and can never be changed.
You created the lastName
variable in Person
with this line:
class Person(val firstName: String, val lastName: String) {
That defines lastName
(and firstName
) as a constant variable. Once it's passed in and assigned when the Person
instance is created, it can't be changed. That makes this statement illegal:
rose.lastName = "Bushnell-Truesby"
To clear up the odd error from earlier, what you need instead is for lastName
to be a mutable variable; you need it to be changeable after initial assignment.
NOTE Not to beat a hairy and somewhat fluffy dog to death, but here is another reason to use mutator over setter; a mutator allows you to mutate a mutable variable. This aligns the terminology much more cleanly than using “setter.”
So change your Person
constructor to use var
instead of val
. This indicates that firstName
and lastName
can be changed:
class Person(var firstName: String, var lastName: String) {
Now you should be able to compile the program again, without error. In fact, once you've done that, make a few other tweaks. You want to end up with your code looking like Listing 1.7.
LISTING 1.7 Using mutable variables
class Person(var firstName: String, var lastName: String) { var 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") println(brian) // Create another person val rose = Person("Rose", "Bushnell") println(rose) // Change Rose's last name rose.lastName = "Bushnell-Truesby" println(rose) }
Here, fullName
has been made mutable, and there's a little more printing in main
. It should compile and run without error now.
But wait! Did you see your output? There's a problem! Here's what you probably get when you run your code:
Brian Truesby Rose Bushnell Rose Bushnell
Despite what Meat Loaf had to say about two out of three not being bad, this is not great. Why is Rose's name in the last instance not printing with her new last name?
Well, to solve that, it's going to take another chapter, and looking a lot more closely at how Kotlin handles data, types, and more of that automatically running code.
2 It's Hard to Break СКАЧАТЬ