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

      Terminology Update: Functions and Methods

      A few specifics on terminology again. A function is a piece of code that runs. main is an example of a function. A method is, basically, a function that's attached to an object. Put another way, a method is also a piece of code, but it's not “stranded” and self-standing, like a function is. A method is defined on an object and can be run against a specific object instance.

      NOTE In much of the official Kotlin documentation, there is not a clear distinction drawn between a function and a method. However, I've chosen to draw this distinction because it's important in general object-oriented programming, and if you work or have familiarity with any other object-based language, you'll run across these terms. But you should realize that in “proper” Kotlin, all methods are functions.

      That last sentence is important, so you may want to read it again. It's important because it means that a method can interact with the object instance. For example, a method might want to use the object instance's property values, like, say, a first name and last name. And with that in mind, back to your code!

      Print an Object (and Do It with Shorthand)

      You can run the println function at any time, and you just pass it something to print. So you could say:

      println("How are you?")

      println(brian.toString())

      down to just this:

      println(brian)

      In the latter case, Kotlin sees an object passed to println() and automatically runs brian.toString() and passes the result on for printing. In either case, you'll get output that looks something like this:

      Person@7c30a502

      That's not very useful, is it? It's essentially an identifier for your specific instance of Person that is useful to Kotlin internals and the JVM, but not much else. Let's fix that.

      Override the toString() Method

      One of the cool things about a class method is that you can write code and define what that method does. We haven't done that yet, but it's coming soon. In the meantime, though, what we have here is slightly different: a method that we didn't write code for, and that doesn't do what we want.

      In this case, you can do something called overriding a method. This just means replacing the code of the method with your own code. That's exactly what we want to do here.

      First, you need to tell Kotlin that you're overriding a method by using the override keyword. Then you use another keyword, fun, and then the name of the method to override, like this:

      override fun toString()

      NOTE Earlier, you learned the difference between a function and a method. And toString() is definitely a method, in this case on Person. So why are you using the fun keyword? That looks an awful lot like “function,” and that's, in fact, what it stands for.

       The official answer is that Kotlin essentially sees a method as a function attached to an object. And it was easier to not use a different keyword for a standalone function and an actual method.

      But, if that bugs you, you're in good company. It bugs me, too! Still, for the purposes of Kotlin, you define both functions and methods with fun.

      But toString() adds a new wrinkle: it returns a value. It returns a String to print. And you need to tell Kotlin that this method returns something. You do that with a colon after the parentheses and then the return type, which in this case is a String :

      override fun toString(): String

      class Person(firstName: String, lastName: String) { override fun toString(): String { return "$firstName $lastName" } }

      This looks good, and you've probably already figured out that putting a dollar sign ( $) before a variable name lets you access that variable. So this takes the firstName and lastName variables passed into the Person constructor and prints them, right?

Snapshot of 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) {

      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.

      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

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