self
keyword.We’re going to continue to use the Cat
class that we wrote in the previous lesson. Let’s paste the code here, so it’s handy for you to reference as we go along:
class Cat { Name as String Species as String Weight as Float Color as String func Walk() -> String { return "The cat is walking" } func Eat(FoodType) -> String { if FoodType == "CatFood" { return "The cat eats his food" } if FoodType == "DogFood" { return "Cats don't eat dog food!" } } func Sleep() { Display "The cat is sleeping" } }
Acting On An Object Within The Object Itself
Look closely at the Walk
method. It returns “The cat is walking”. Which cat? Reading the return value in a program, we wouldn’t know. What if our program created 20 cats? How could we know which one is walking? If we (as programmers) read the source code, we’d work it out, but our users can’t read the source code. They don’t even have access to it.
Let’s create an object myCat
and set its Name
property to "Athena"
.
myCat = new Cat myCat.Name = "Athena"
(you knew how to do that, right?)
We need to figure out a way to return Athena is walking
rather than The cat is walking
. Let’s modify the Walk
function as follows:
func Walk() -> String { message = Name + " is walking" return message }
In the code above, we tried to concatenate the property Name
with the String " is walking"
. Name
being of data type String, you know that the +
is the concatenation operator and that it can merge two Strings.
Unfortunately, this wouldn’t work in many programming languages. That is because upon seeing Name
, the computer would look for a Name
variable within the Walk
method and none exists. What we’d ideally like to do here, is to instruct Mr Computer to use the Name
property within the Cat
class. The good news is that there’s a way to tell the computer to use a property from within the class. We do so by using the keyword self
. It’s auto-descriptive: self
means the current class
. We would therefore rewrite the method like this:
func Walk() -> String { message = self.Name + " is walking" return message }
By prefixing the Name
property with self
and using the dot operator, we are telling the computer to use the Name
property belonging to the current class. The current class being Cat
as that is where we are currently writing our code. Now lets write a program using our updated Walk
method:
import Animals func Main() { myCat = new Cat myCat.Name = "Athena" myCat.Species = "Tabby" myCat.Weight = 8.7 myCat.Color = "Black" Display myCat.Walk() }
When we run the above program, this is what would be displayed on the screen:
Athena is walking
Much better! The user knows which cat is walking. Let’s do a quick recap; we created a new cat object, set its properties, one of them being the name we set to Athena and then, displayed the return value of the Walk
method. As we modified the Walk
method to concatenate the value of the Name
property with is walking and return it, the output of our program was indeed Athena is walking.
Setting Properties At Creation Time
When we wrote our program, we had to set each property of the new cat object manually:
[ ... code omitted for brevity ...] myCat = new Cat myCat.Name = "Athena" myCat.Species = "Tabby" myCat.Weight = 8.7 myCat.Color = "Black" [ ... code omitted for brevity ...]
That’s a lot of code to write. Let’s learn how to reduce it, using a constructor to help us.
First of all, consider what would happen if we forgot to assign a value to the Name
property and then called the Walk
method? There’s no value for Name
so what would the program display? A massive error! Depending on the language, you’d get a variation of the error message the Name property has not been set and therefore can't be used
before the computer would overheat, create a giant black hole and destroy the earth in the process (ok – we might be exaggerating just a touch!). We wouldn’t want that, right?
Properties can have default values. These are initial values that they default to if we haven’t explicitly changed them, after creating a new object. We assign default values by adding a special method named init
to our class. It’s special because the computer will know to call this method right after you create an object with the new
keyword. new
not only creates an object from a class, it also calls the init
method. This init
method is called a constructor.
Let’s modify our class to add a constructor. The constructor task will be to set initial values to each property:
class Cat { Name as String Species as String Weight as Float Color as String func init() { self.Name = "Some cat" self.Species = "Unknown" self.Weight = 8 self.Color = "White" } func Walk() -> String { return "The cat is walking" } func Eat(FoodType) -> String { if FoodType == "CatFood" { return "The cat eats his food" } if FoodType == "DogFood" { return "Cats don't eat dog food!" } } func Sleep() { Display "The cat is sleeping" } }
In the above code, we added a constructor, represented by the init
method. The name of the method, init
is a convention and is part of our pseudocode language syntax. When we create an object using the new
keyword, the computer will automatically attempt to call the init
method”. If the constructor method has a different name, the computer won’t be able to find it.
Note: In our pseudocode, we chose to use
init
as the constructor method name.init
happens to be the name used in the Swift language. Other languages have different conventions. For example, in the Ruby language, the constructor would be namedinitialize
, in the Python language, it would be named__init__
.*
We also just learned about the self
keyword and as you can see in the code above, we used it in the constructor to say access the property in the current class.
Now, consider the program below. Can you figure out what would be displayed on the screen after running this program? Try not to peek!
import Animals func Main() { myCat = new Cat Display myCat.Walk() Display myCat.Species }
Here’s what would be displayed:
Some cat is walking Unknown
This is because we now have default values for properties set up. When were these values assigned to the properties of myCat
? That’s right, just after calling new Cat
because new
not only creates a new object but also implicitly calls the init
method.
So as programmers writing a program that makes use of the Cat
class, from now onwards we would only manually set the properties that need to be changed and that we don’t want to have the default values:
import Animals func Main() { myCat = new Cat myCat.Name = "Aegon" myCat.Species = "Siamese" Display myCat.Walk() Display myCat.Species }
There is much, much, much more to constructors than simply setting default values. In fact, there are techniques for assigning default values to properties without even using constructors. Each programming language handles these concepts slightly differently and we’ll study this in more detail when we learn a real programming language.
You’re making amazing progress! These last few lessons have been hectic, but it’s immensely satisfying when these concepts start to come together in your mind. Keep at it!
Summary
You now understand what self
means: use a property or a method within the current class. You also know that you can set initial default values for objects by adding a constructor to a class. The constructor, represented here by the special init
method, is called by the new
keyword when we create an object.
Important Words
self
- Constructor
- Default values
init
Exercise
In the previous lesson on objects, you created a new class for an animal of your choice. Now is the perfect time to add a constructor to that class and modify its methods to give the users more information about the objects that will be created from it. GO! Share your code in the Forums! We’ll all provide you with feedback!