Lesson 10Phase 2: Objects
Why objects? Class vs object
The problem objects solve, and the difference between a blueprint and the thing built from it.
By BasithUpdated 55 min
- why OOP
- class
- object
- instance
- blueprint analogy
- state and behavior
You can already write programs that work. Variables hold values, if and switch make decisions, loops repeat, and arrays and lists hold many values at once. So here is a fair question to start with: if all of that works, why does Java keep talking about something called an object?
- Explain, in plain words, the problem that objects exist to solve.
- Tell a
classapart from anobjectwithout reaching for jargon, and say what an instance is. - Look at a piece of data in a program and say what its state and its behavior are.
- Read your first class-and-object program, step through it, and predict what it prints.
Start with the mess#
Imagine you are writing a small program for a bank. It needs to keep track of one customer's account: their name, their balance and the account number. With the tools you have so far, you would reach for separate variables.
public class Main { public static void main(String[] args) { String name = "Aisha"; int accountNumber = 1001; double balance = 500.0; balance = balance + 200.0; System.out.println(name + " now has " + balance); }}That works. Now the bank gets a second customer, and a third. With separate variables, you are pushed into something like this:
public class Main { public static void main(String[] args) { String name1 = "Aisha"; double balance1 = 500.0; String name2 = "Ben"; double balance2 = 300.0; String name3 = "Carmen"; double balance3 = 900.0; balance2 = balance2 + 200.0; System.out.println(name2 + " now has " + balance2); }}Look at what is happening. The same idea, a customer, is smeared across many loose variables with numbers stuck on the end of their names. Nothing ties name2 and balance2 together except that you, the human, remember they belong to the same person. The computer has no idea. Add a fourth customer and you copy the pattern again. Add a field, say a phone number, and you have to add it three times, once per customer, and never forget one.
Arrays help, up to a point#
You know a better tool than numbered names: arrays. One array holds the names and another holds the balances, and each customer sits at the same index in both.
public class Main { public static void main(String[] args) { String[] names = {"Aisha", "Ben", "Carmen"}; double[] balances = {500.0, 300.0, 900.0}; balances[1] = balances[1] + 200.0; for (int i = 0; i < names.length; i++) { System.out.println(names[i] + " has " + balances[i]); } }}This is an improvement. One loop now handles any number of customers, and a deposit for Ben is a single line. But the link between a name and its balance is still only a shared index that you keep in your head. Arrays that line up like this are called parallel arrays, and they break as soon as one of them changes without the other.
public class Main { public static void main(String[] args) { String[] names = {"Aisha", "Ben", "Carmen"}; double[] balances = {500.0, 300.0, 900.0}; // Put the biggest balance first: swap places 0 and 2. double temp = balances[0]; balances[0] = balances[2]; balances[2] = temp; for (int i = 0; i < names.length; i++) { System.out.println(names[i] + " has " + balances[i]); } }}The bank wants the biggest balance at the front of its list, so this program swaps two balances. What does it print?
It prints Aisha has 900.0, Ben has 300.0 and Carmen has 500.0. The balances moved and the names stayed put, so Aisha now owns Carmen's money. Java had no way to know that names[0] and balances[0] belonged together. Sorting the customers, removing one, or adding an array of phone numbers would all need the same care in every array, every time.
Key ideaData that belongs together is not held together. Nothing in the program is “a customer”: a customer exists only in your head, as a name and a balance that happen to share an index.
{"name": "Ben", "balance": 300}, or in a class of your own. A Java class does that job, with one difference: it lists every field and its type up front, so every customer has exactly the same fields.The idea: bundle the data with the things you do to it#
Here is the move that object-oriented programming makes. Instead of loose variables, you describe one kind of thing once: what fields it has and what it can do. A customer has a name and a balance. A customer can deposit money. The state (the data) and the behavior (the actions) are bundled into a single unit.
That description, the shape of “a customer”, is called a class. It is a blueprint. It is not a customer itself, the same way an architect's drawing of a house is not a house you can live in. From one blueprint you can build as many real customers as you want, and each real one is called an object.
The cookie cutter
A cookie cutter is a class. It describes the shape. It is made once. You cannot eat it. Each cookie you press out with it is an object: a real, separate thing, all sharing the same shape but each with its own existence. Eat one and the others are untouched. Change the dough on one and the others do not change.
An object built from a class is also called an instanceof that class. Aisha's account and Ben's account are two instances of Customer, the way two cookies are two pressings of one cutter. Building one is called instantiatingthe class. The two words just mean “an object made from this class” and “making one”, and you will meet them in error messages and documentation.
Cookie on it.class.new. It is an instance of its class.Customer, and main runs new Customer() three times. How many Customer objects exist?Your first class and object, running#
Here is the smallest complete program that defines a class and makes objects from it. Read it once, then press Run and step through it. Watch the memory view under the code when new runs: a new Customer object appears there, with its fields at their starting values.
public class Main { public static void main(String[] args) { Customer a = new Customer(); a.name = "Aisha"; a.balance = 500.0; Customer b = new Customer(); b.name = "Ben"; b.balance = 300.0; System.out.println(a.name + ": " + a.balance); System.out.println(b.name + ": " + b.balance); }} class Customer { String name; double balance;}Two things are worth saying out loud. First, Customer is written once at the bottom: the blueprint. Second, new Customer() appears twice in main, and each one makes a separate object, so the memory view ends up with two Customer objects. Setting a.name does not touch b.name. They are different cookies from the same cutter. The . (dot) reaches into one specific object to read or set one of its fields.
a.balance reads as “the balance belonging to a”. Whenever you see a dot between a variable and a field, picture reaching into that one object and pointing at one field inside it. You will use this constantly.Two variables, one object#
The variable a does not hold the customer object itself. It holds a referenceto it, which you can think of as the object's home address; the object lives elsewhere in memory. So two variables can hold the same address and point at the same object. Step through this program and watch the memory view:
public class Main { public static void main(String[] args) { Customer a = new Customer(); a.name = "Aisha"; a.balance = 500.0; Customer sameOne = a; sameOne.balance = 750.0; System.out.println(a.name + ": " + a.balance); }} class Customer { String name; double balance;}new runs once, so the memory view only ever holds one Customer object. The line Customer sameOne = a; makes a second variable that points at that same object. The balance set through sameOne is the balance a reads, which is why the program prints Aisha: 750.0. Two names, one customer. This matters a lot later, and it gets a careful look in creating classes and objects and again in the this keyword and object references.
State and behavior: the two halves of every object#
So far Customer only has state, the fields. The other half of the idea is behavior, the actions an object can do with its own data. Depositing money is a thing a customer does, so it belongs inside the class, next to the data it works on.
public class Main { public static void main(String[] args) { Customer a = new Customer(); a.name = "Aisha"; a.balance = 500.0; a.deposit(200.0); a.deposit(50.0); System.out.println(a.name + " has " + a.balance); }} class Customer { String name; double balance; void deposit(double amount) { balance = balance + amount; }}deposit is a method: a named action that belongs to the class. Notice that it just says balance, not a.balance. Inside the class, the object is already talking about itself, so balance means “my own balance”. When you call a.deposit(200.0), the action runs on a's balance, so this prints Aisha has 750.0. If you had a second customer and called b.deposit(...), the very same method would run on b's balance instead. One description of the behavior, reused by every object.
Key ideaAn object is state and behavior kept together: the data, and the actions that belong with that data, in one unit.
You have used objects like this already. In ArrayList, scores.add(7) asked one list to change its own contents, and scores.size() asked it how many values it held. The list kept its values (state) and knew how to work with them (behavior). Someone wrote the ArrayList class once, and every list you make is an instance of it. Now you write classes of your own.
Playlist class. Which of these is behavior rather than state?Aisha has 700.0. The indentation of each line is a clue to where it belongs.Tap a line, then tap where it should go. Or use the arrows.
300.0. Deposit 50.0 into Ben's account only, then print Ben's line in the same format as Aisha's. Aisha's balance must stay at 500.0.a.balance = -999 from outside and break the account. Protecting an object from being put into a nonsense state is the point of encapsulation, and building it correctly from the first moment is the point of constructors. Methods like deposit get a full lesson of their own in methods. You do not need any of these yet.Try it
Answer each one in your head or on paper first, then open the answer.
class is and what an object is, using the cookie cutter only if it helps.a and b. After both are set up, the line a.name = "Zara"; runs. What does b.name print now, and why?Dog class. You are designing the blueprint, not any one dog.String[] phones, and later removes Ben from all the lists. Name one way this could go wrong that a Customer object would prevent.Practice
Work through these on your own. Each one builds on this page.
Book class. Write down its fields (state) and at least one action (behavior). Do not write Java yet, just the blueprint in plain words. You turn it into Java in the next lesson, creating classes and objects.b, deposit different amounts into each, and print both. Confirm that depositing into a never changes b.name and balance together inside one object better than loose balance1, balance2, balance3 variables, or two parallel arrays? Think about what happens when the bank has a thousand customers and decides to sort them.Further reading#
Spotted a mistake, or a part that did not make sense? Report it by email