A method is a function defined inside of a class. Methods are capabilities that are specifically defined for instances of that class. Think of properties of a class as adjectives and methods of a class as verbs.
Since we define a method inside of a class, we call it on an object of that class by using dot operator on the object, followed by the method name then our parentheses with the necessary arguments.
Here's what that would look like:
class Name { // defining the method methodName(parameter: type): returnType { // body; } } // calling the method object.methodName(argument);
Here's an example of a class with a method and how we call the method on an object:
import { print } from "introcs"; class Dog { name: string = ""; age: number = 0; makeNoise(): void { print("woof woof"); } } let spot: Dog = new Dog(); spot.makeNoise(); // prints: "woof woof"
This works nicely, but we can do so much more with methods. If we want a method that can access and change an object's properties, we use the "this" keyword. To learn more about this and see some examples, check out the "this" page!
When a method is called on an object, the steps that follow are:
There are a lot of times we need to access several properties or methods of an object to get a desired result or value, and many times we're able to chain these together. If we're making multiple method calls, we can sometimes chain them together. This is often used with filter, map, and reduce, but it can be used in other situations as well.
If a method call returns an object that has its own methods, we can just keep going in the same statement and call that returned object's methods right on the original method call! Let's go through an example to get a better feel for how it can work:
class Team { teamFirst: string = ""; teamLast: string = ""; makeName(): string { return this.teamFirst + " " + this.teamLast; } } class Mascot { team: Team; cheer(name: string): string { return "go " + name + "!!!"; } } let heels: Team = new Team(); heels.teamFirst = "tar"; heels.teamLast = "heels"; let rameses: Mascot = new Mascot(); rameses.team = heels; print(rameses.cheer(rameses.team.makeName()).toUpperCase());
There's a lot going on in this example, so we'll go ahead and break it down.
First, we have our Team class, with two properties and a method. Looking at this method, we know it'll have to be called on a Team object (since it's defined in the Team class) and that it'll return a string.
Next, we've got our Mascot class, with a team property of type Team and a cheer method. Looking at this method, we know it'll have to be called on a Mascot object and that it'll return a string.
After defining these classes, we start to use them. We make our heels variable of type Team and initialize it to be a new Team object. Then, we assign that object's properties to be "tar" and "heels". Next, we make rameses, our Mascot object, and assign its team property to be a reference to heels, which is the Team object we just created. We're allowed to do this since heels is of type Team and the team property in the Mascot class is also of type Team.
Finally, within our print statement we get to the fun part of accessing properties, calling methods, and chaining stuff together. Woohoo!
print(rameses.cheer(rameses.team.makeName()).toUpperCase());
The first thing we see here is that we're starting off with our rameses object, which we know is of type Mascot. We're calling the cheer method on rameses, which is okay since cheer is a method defined in the Mascot class. Looking at the definition of the cheer method, we know it takes in a string, so we know whatever is inside the parentheses of the cheer method call must evaluate to a string. Let's take a closer look at what's inside these parentheses.
print(rameses.cheer(rameses.team.makeName()).toUpperCase());
Right now, we're focusing on the rameses.team.makeName() part of this. Here's where it gets interesting with chaining. We start with our rameses Mascot object and access the team property. rameses.team evaluates to heels, so we can think of our original print statement like this:
print(rameses.cheer(heels.makeName()).toUpperCase());
Great! The next piece now that we've got heels is calling the makeName method. Accessing the team property of rameses, rameses.team, evaluated to heels, a Team object, and we know by looking in our Team class that we call the makeName method on Team objects, so we're on the right track! Looking at the makeName method, we see that it doesn't require inputs and that it returns the string that results from concatenating this.teamFirst with a space and this.teamLast. We know makeName was called on the heels object, so this refers to the heels object. As a result, this.teamFirst evaluates to "tar" and this.teamLast evaluates to "heels", so the string returned by the makeName method is "tar heels". So we can substitute this back in to our print statement:
print(rameses.cheer("tar heels").toUpperCase());
Now that we've evaluated the expression and figured out the string argument for the cheer method, we'll go ahead and work through this method call. Calling cheer on rameses with the string "tar heels" returns the string "go tar heels!!!". We'll substitute this back in:
print("go tar heels!!!".toUpperCase());
Now we've got it down to one string and a method call. Here, we're calling the built-in string method toUpperCase on the string "go tar heels!!!". This results in the string "GO TAR HEELS!!!", which we'll substitute in:
print("GO TAR HEELS!!!");
Now, we print "GO TAR HEELS!!!" and we're done!