Classes and Instances#
The Cookie Cutter: A Class#
A class
gives you structural information. What will be the information that you will need here? All the contacts in your contact list have a name, a picture and a phone number. Imagine it in tabular form:
Pic | Name | Phone Number | |
---|---|---|---|
Kira Nerys | +881 604587 | kira.n@bajor.mil.example | |
Julian Bashir | +881 698028 | cmo@ds9.starfleet.example | |
Worf, Son of Mogh | +881 805411 | worf@house-of-martok.example | |
Jadzia Dax | +881 870212 | curson2265@yahoo.example |
The columns of that table are basically attributes of a person that we might want to work with. A class has to accommodate those, so it could look like this:
- Phone numbers can contain all kinds of weird things that are not numeric, and we usually don't want to do calculations with them, so we're defining this as a
String
— even though we're saying phone number.
class
is a new keyword in tha Java Programming language. It tells the computer (and us) that what follows will be a new class of things. We're calling ours Contact
1. Then a new block of code { ... }
follows, and it contains all the structural and behavioral things of our class.
Where are Nerys and Julian, though?
We're not at this part, yet. Currently, we're thinking in very abstract terms. All the things that all Contact
s have in common.
Within our class' block of code, we define the attributes we want every entry to be able to store. If this looks like declaring variables, then you're absolutely right! This is exactly what we are doing. We're just saying "these variables here belong the each instance of our class!
The Cookie: An Instance#
With the class above, we could now move on to our cookies. Or the actual contacts that use the structural information in Contact
. We will now create and instance of our class:
Contact bashir = new Contact();
bashir.picture = loadImage("julian.jpg");
bashir.name = "Julian Bashir";
bashir.phoneNumber = "+881 698028";
bashir.email = "cmo@ds9.starfleet.example";
println(bashir.name + " (" + bashir.phoneNumber + ")");
// prints: Julian Bashir (+881 698028)
That first line somehow uses Contact
like a data type?! YES! You get to define your own data types! We declare a new variable of type Contact
, we call our variable bashir
and then we assign a value to it. That new value is new Contact()
— the new
is important here, this is how we create a new instance from our Contact
class!
After that first line, we have an empty Contact
object which is available in the bashir
variable. The next four lines now set a few fields. This does not have to be directly follow it (in fact we'll see very different examples later on), but I wanted to show you how to access the attributes of your new object. The notation with the .
is how you get to all the attributes in your bashir
contact. You can read or write these like regular variables.
Note
You can't simply use picture
or email
, you always have to write the full bashir.email
or bashir.picture
, because these attributes live within the bashir
object (or instance, both terms are correct).
Just Like the String
Examples!#
If that .
looks familiar, to you, you may be on the right track! You just saw a very similar example on the String
s that you were working with. The reason for that is very simple: in Java String
is also a class, and you create instances of String
whenever you work with them.
If you access the .length
of a string, you're looking up an attribute of String
.
Defining Methods on our Class#
So far, we only store data, but I promised you behavior, too. When a function lives inside a class, we call this a method. Let's add a few to our class:
class Contact {
PImage picture;
String name;
String phoneNumber;
String email;
void show() {
push();
image(picture, 0, 0, 100, 100);
textSize(25);
text(name, 110, 30);
textSize(16);
text(phoneNumber, 110, 55);
text(email, 110, 80);
pop();
}
}
I added a method called .show()
, it returns nothing (so it has a void
return type), and it contains a few lines of fairly basic drawing code that should not give you any trouble at all. Please note how this sits inside our Contact
class, though!
In this example, we're also accessing picture
and the other attributes just as if they were regular old variables.
Which attribute gets used?
Our class doesn't know anything about how and where it will be used. In our example, it does not know about the bashir
instance, and it should not need to know about it!
But the class is (usually) used for many instances - how does it know which name
attribute it should output? We should print the name
that's attached to the object we're working with. If we use our new .show()
method with bashir
, it will be "his" show-function using "his" name
, picture
and other attributes.
Let's add a second instance to our example and see it in action:
Here, we have two Contact
instances (bashir
and kira
) and on lines 20 and 22 we call .show()
once for him and once for her. In between we just use translate()
to they don't sit in exactly the same spot.
When we call .show()
on kira
, all her info will be used, and when we call .show()
on bashir
, all his info will be there. The class itself does not really care about that. It just keeps the instances separate and can stay happy and abstract.
The sketch above produces this output:
Common Advice#
Naming Conventions for Classes, Attributes and Instances#
Usually, your class names will be nouns (Contact
, Player
, GameObject
, Cart
, ImageLoader
, LocalDateTime
...). The common convention is, to write a class name with a capital first letter and then continue with CamelCase for each subsequent word.
If you have trouble coming up with a good name, your class might be doing too many things and you might want to split it into two or more parts.
Your attributes names will also usually be nouns (.name
, .phoneNumber
, .color
) but there might be more abstract concepts in there, too (.x
, .y
for example). These generally look exactly like variables, so in Java, we're using lower case camelCase
for these. Beginners often duplicate information we already have. Please avoid writing (we already know it's a contactName
Contact
from its type).
Your method names will most often be verbs or terms that convey some kind of action like .show()
, .delete()
, .transfer()
, .getChar()
. .toString()
(and similar things) is also a common name for a conversion of some kind. We use the lower case camelCase we've been using for functions, too.
Instances can be basically any name you can recognize, in the code examples above, I chose to use the names of the characters in question, but it might just as well have been player
or something else. All the rules for variables you already internalized apply here. Instances, from that perspective, are just another variable that has slightly more to offer.
1 Class → 1 File#
I just introduced to you how you can split up your projects, and this was by design. It is extremely common to put each class in its own tab (or file). I would strongly recommend you adopt this practice. This is also why the previous example is split into two tabs in this article.
Relevant excerpt from Learning Processing#
(the section starts at 4:02:30 and runs through 4:25:18, the video should start and stop on these automatically. It also already covers part of a thing called constructor which will get its own article.)
-
We could also have chosen
Person
orAddressBookEntry
or anything else, really. But I didn't choosePerson
because your typical contact list will also usually have entries for companies, andAddressBookEntry
is slightly long, soContact
won ↩