41039 · Programming 1
Week 5 · 41039 Programming 1

Classes, Objects and Enums

Week 4 split a program into methods. This week the methods get something to belong to: objects, bundles of data together with the code allowed to touch it, built from classes. You will write your own classes in Java and Python, see what new and this really do, meet enums — types with a fixed set of values — and see what Java’s switch has grown into since Week 2.

5 Ed lessons Java Python
Week 5 · Interactive

The lecture, then the practice

Choose a section from the list to open it — or use the arrow keys once the list has focus. Every code example explains itself: hover over an underlined part (or tap it) to see what it does. Run runs it; ✎ Edit opens it in an editor to change it and break it on purpose. Several are meant to fail — read what the compiler says before you fix them.

01The ideas behind OOP

1.1A brief history

Object-oriented programming (OOP) is a broad family of ways to design programs, centred on one idea: bind data to the code that is allowed to manipulate it, in a single entity called an object.

Historically the idea grew, possibly ironically, out of the functional language Lisp in the late 1950s and early 1960s. Simula introduced many of the concepts still in C++ and Java — classes, dynamic binding, inheritance — with syntax close to Algol 60, which is why it reads fairly easily to a Java programmer. Smalltalk was designed as an OO language from the ground up and is often called the first “true” one, but Simula has had the greater effect so far — not least because Bjarne Stroustrup used it during his doctoral work and then built its ideas into C++.

Portrait of Bjarne Stroustrup

The class concept allowed me to map my application concepts into the language constructs in a direct way that made my code more readable than I had seen in any other language.

Bjarne Stroustrup, A History of C++: 1979–1991, HOPL-II, 1993 — on writing his PhD simulator in Simula Portrait: Victor Zavyalov / ICPCNews, 2013 · CC BY 2.0

OOP became the dominant paradigm in the 1990s, with C++, the arrival of Java, and a software industry that needed modular, reusable, maintainable programs at large scale. Like any tool it can be used badly; used well, it is a very powerful way to build large software that can be extended without being rewritten.

Did you know?

Two Turing Awards in three years went to object orientation. The 2001 award went to Ole-Johan Dahl and Kristen Nygaard “for ideas fundamental to the emergence of object-oriented programming, through their design of the programming languages Simula I and Simula 67”; the 2003 award to Alan Kay for “leading the team that developed Smalltalk”, among other things. Both Stroustrup and James Gosling, Java’s creator, have named Simula as a major influence. Source: Wikipedia — Turing Award and Simula.

Kristen Nygaard, co-designer of Simula, photographed in 1997
Kristen Nygaard. Photo: Jorge Stolfi, 1997 · public domain

1.2The four pillars

“Object-oriented” covers anything whose fundamental unit is the object, but almost every OO language rests on four principles:

PillarWhat it means
EncapsulationData is enclosed in objects. That gives it context, and control over how it is accessed and changed.
AbstractionImplementation details are hidden from the outside. Two implementations that do the same job are interchangeable; users only deal with the abstraction.
InheritanceObjects can inherit properties from other objects, so subtypes exist, share what they have in common and differ only where they need to.
PolymorphismOne thing, many “shapes”: different implementations of the same method, objects with several types, type information abstracted away.

They are not completely separate — encapsulation enables abstraction, inheritance supports polymorphism, polymorphism supports abstraction. Under all four sits a vaguer but stronger idea, shared with the modular programming that came before OOP: any unit of a program should not have to care how the rest of the program works in order to work correctly.

1.3Encapsulation

The simplest pillar to get hold of, though its payoff only really shows when you build something large or fix someone else’s code. This BankAccount (the one from lab 5) encapsulates two pieces of data and offers methods for controlled access to them. The balance is kept as a whole number of cents:

  1. new makes a BankAccount object and runs its constructor (lines 20–23) with these two arguments. The f makes 100.10 a float literal; without it, it is a double and will not fit the float parameter.
  2. main learns the balance only by calling a public method, which returns it as a float number of dollars. Nothing in main reveals that the account keeps cents.
  3. Each call rounds 0.01 × 100 to exactly 1 cent, so the int balance grows by exactly 1000 cents, to $1,000,010. Keep this loop in mind for 1.4.
  4. The blueprint for every account object: two pieces of data (lines 17–18) together with the only methods allowed to touch them. Binding data to the code allowed to change it is the central idea of OOP (1.1).
  5. Only code inside BankAccount may use accountName, or balance on line 18, which is private too. Runner’s main is outside, so it must go through the public methods.
  6. An int holds whole numbers exactly, so $100.10 is kept as 10010 and adding or subtracting cents never loses anything to rounding.
  7. Same name as the class and no return type, not even void. It runs once, when new creates the object, and gives the fields their first values.
  8. The parameter has the same name as the field, so plain accountName means the parameter. this.accountName is the field of the object being built.
  9. Multiply to get cents, still a float, then round to the nearest whole number. Given a float, Math.round returns an int, so the result goes into balance with no cast.
  10. The cast applies to this.balance alone, so the division is done in float and keeps the cents: 11919 becomes 119.19. Without the cast, int division would give 119.
  11. The amount is turned into whole cents before it is subtracted. No parameter is called balance, so the plain name means the field; this. is optional here.
  12. A method may share a field’s name; the brackets tell Java which is meant. It hands out the name, and no method changes it, so outside code can read the name but never alter it.

Two classes in one file: only one may be public, and the file is named after it — the Week 1 rule. BankAccount has no access modifier, which is what lets it share the file.

accountName and balance are private, so code outside the class cannot interfere with them except through the methods. Try it: this main reaches for the balance directly.

  1. The constructor is public, so any class may create an account. But a compile error stops the whole file, so not even this line runs.
  2. main is in Runner, and balance is private to BankAccount, so the compiler refuses the assignment (javac: balance has private access in BankAccount). Sharing a file does not help: private means this class only.
  3. This cut-down class has only a constructor. With no public methods, code outside the class cannot read or change balance at all.
  4. Access to balance is limited to code written inside BankAccount’s braces. Remove this word and line 4 compiles — and main can set any balance it likes.
  5. The constructor belongs to BankAccount, so it may assign balance freely. The same field is out of bounds in main.
Safety, not security

private is there to stop accidental interference, not a determined attacker. It is about safety, and a step towards abstraction: code that uses BankAccount never needs to know how the data is stored inside, only which public methods it can call.

1.4Abstraction — and we tested the claim

Abstraction says you should not have to care about the insides of something when they do not matter to what it does. A clockwork watch, a digital watch and a phone all present the time; you use them interchangeably whether there are gears inside or a connection to an atomic clock.

For code, that means the rest of a program should not have to change when an implementation does. The Ed lesson offers a second BankAccount that stores a float instead of cents, and says the lab program could “probably (I haven’t tested it)” use it unchanged. So test it. Same main, word for word; only the inside of BankAccount differs:

  1. main depends only on the names, parameters and return types of the constructor and the four public methods. Those are identical, so main compiles without a change.
  2. In the cents version this loop added exactly 1000 cents. Here each call does a float addition that changes nothing (line 34), so Bach’s balance never moves from 1000000.0.
  3. The field now holds dollars directly, as a float. Because it is private, no code outside the class could depend on it — which is why the swap is invisible to main.
  4. No conversion to cents. But 100.10f cannot be held exactly: the nearest float is 100.09999847…, which currentBalance later rounds back to the cent.
  5. Turns dollars into cents and rounds to the nearest whole number. Given a float, Math.round returns an int.
  6. The cast applies to the int from Math.round, so / 100 divides in float and keeps the cents. Without it, int division would drop them.
  7. Each subtraction and addition rounds its result to the nearest float. Near Linh’s 100 dollars those errors are far below a cent, and currentBalance rounds them away.
  8. Near 1,000,000 the nearest floats are 1000000.0 and 1000000.0625. The exact sum, about 1000000.01, is much closer to the first, so the result rounds back to the old balance.

Linh’s account agrees with the cents version, to the cent. Bach’s does not: a thousand one-cent deposits into a million-dollar account simply vanish. A Java float is an IEEE 754 32-bit number with only about seven significant digits, and near 1,000,000 the gap between one float and the next is 0.0625 — so adding 0.01 rounds straight back to where it started.

What abstraction does and does not promise

The swap worked exactly as abstraction says it should: main compiled and ran without a single change. What abstraction cannot do is make the new implementation correct. That is why the Java lesson suggests storing money as an int number of cents — and why “I haven’t tested it” is a sentence worth never leaving in your own code.

1.5Inheritance and polymorphism, briefly

Inheritance arrives properly in the next few lessons. In Java it comes in two forms, class-based inheritance and interfaces, and it does two jobs at once: a child class reuses its parent’s data and methods instead of reimplementing them, and a child can be treated as the same kind of thing as its parent.

Polymorphism comes in three basic forms:

  • Ad-hoc — the same method name applied to different parameter lists. You have used it constantly: it is Week 4’s overloading, and the reason System.out.println has ten versions.
  • Parametric — type information abstracted out, so code can store or move objects without caring much what type they are. Coming very soon.
  • Sub-type — an object can be treated as having the type of any of its parent classes. Also coming very soon.
03 · This week

What to actually do

On Ed, work through the five Week 5 lessons. This order matches the sections above:

  1. Fundamentals of Object Oriented Programming — section 1
  2. Classes and Objects in Java — sections 2 to 4, including the four pizza-shop parts and their forkable workspaces
  3. Classes and Objects in Python — sections 5 and 6
  4. Enums in Java (and Python sort of) — section 7
  5. Advanced switch Statements in Java — section 8
Run the new Java on Ed

Records, switch expressions, pattern matching and when need Java 14 to 22; this page’s console runs Java 8. Those examples are printed with their real output — paste them into Ed to run them, and change them.

Deadlines

Assessed lab exercises are due 11:55pm the Monday of the following week, and you must pass all test cases in an exercise to get its marks. Canvas → Assignments is authoritative for what is due and when; where this page differs, Canvas and the announcements win.

If you only do one thing

Write one small class of your own from nothing — private data, a constructor, two methods — and use it from a main in another class. Then do it again in Python. Everything from here on is built out of that.

Sources

Everything cited on this page

The lecture content comes from the Week 5 lessons on Ed. The links below are for the claims this page adds around them — checking a source yourself is a better habit than trusting any lecture slide, including ours.

Specifications and documentation

Used inSource
1.4The Java Language Specification, Java SE 25, §4.2.3 — float is IEEE 754 binary32; the 0.0625 spacing at 1,000,000 is Math.ulp(1000000f), run on JDK 26
3.1JLS §8.3.1.1 — “exactly one incarnation of the field”
4.1The Java Virtual Machine Specification, Java SE 25, §2.5.4 — the method area
4.2JLS §8.8.9 — “If a class contains no constructor declarations, then a default constructor is implicitly declared”
2–4Oracle — Classes, The Java Tutorials
6.3The Python Tutorial, §9.6 Private Variables — name mangling and the _spam convention
7.2Oracle — Enums, J2SE 5.0 language guide — the int enum pattern, “Not typesafe”
7.3JLS §8.9 — “An enum class has no instances other than those defined by its enum constants.”
7.7Python — Enum HOWTO (aliases; isinstance of members); PEP 435 (enum added in Python 3.4)
8.3–8.5JEP 361 (switch expressions, JDK 14); JEP 441 (pattern matching for switch, JDK 21); JEP 440 (record patterns, JDK 21); JEP 456 (unnamed variables and patterns, JDK 22)
8.4PEP 636 — Structural Pattern Matching: Tutorial — guards

Quotations

Every quotation on this page was checked against a primary source — the original paper or documentation, not a quotation website.

Used inSource
1.1Bjarne Stroustrup, A History of C++: 1979–1991, ACM HOPL-II, 1993, §1 Introduction
1.12001 and 2003 Turing Award citations, as listed in Wikipedia — Turing Award
6.3The Python Tutorial, §9.6 Private Variables

Photographs

From Wikimedia Commons, reused under the licence each one names. Author and licence come from the Commons API rather than from anyone’s memory — see media/fetch-photo.py.

ImageSource
cookie-cutterApple Shaped Cookies (14888835148) — Personal Creations, 2014 · CC BY 2.0
playing-cardsPlaying Cards - number fives — Sudzie, 2021 · CC BY-SA 4.0
kristen-nygaardKristen-Nygaard-SBLP-1997-head — Jorge Stolfi, 1997 · public domain
stroustrupBjarne Stroustrup (2013) — ICPCNews (photographer Victor Zavyalov), 2013 · CC BY 2.0

Articles

Used inSource
1.1Simula — Stroustrup and Gosling acknowledging Simula as a major influence