Sep 18: Classes and Objects


Code discussed in lecture

The code for the Counter class is here: Counter.java. Last class we did a quick overview - class declaration, variable declarations, method declarations, return types, parameters. Now we will go through things in more detail:

Java Types

Probably the biggest change for Python programmers in moving to Java is that you have to declare your variables and say what type each will hold. It isn't that Python didn't have types. It was that Python checked them at run time. Java checks them statically at compile time, and knows that at run time that everything is OK. By saving all of those run time checks Java code is able to run significantly faster than Python code.

So what is a type, and what is it for? At the basic level computer memory is a long sequence of 1's and 0's, each called a bit (BInary digiT). It is broken into eight bit chunks (called bytes), each with its own address. There are may things that you might want to store in a computer: numbers, characters, colors, sounds, wildebeast objects, etc. Even computer instructions are stored in memory. Each "type" of thing has its own encoding as bits. When I was teaching the computer architecture course one of my favorite test questions was to give a 32 bit sequence of 0's and 1's and ask how it would be interpreted if it were a computer instruction, an integer, a string of characters, a color, etc.

When programming in machine language the programmer has to remember what each byte is supposed to represent. If he or she starts treating computer instructions as if they were integers, or integers as if they were computer instructions, bad things happen. (That is what many computer viruses do - they store a bit pattern as data, and then trick the program into running that pattern as code.)

The two things that a type tells us are:

Smalltalk, an early OO languge, has a very elegant solution to the type problem. Everything is an object, and the operations that are valid on the object are precisely those defined by its methods. The methods understand how to interpret the bit patterns. It is elegant, but having to ask a number to add itself to another number via a method call is a lot slower than using the hardware "add" instruction. Smalltalk is slow.

Java therefore has a compromise. Most things are objects whose types are defined by the methods that they implement and the data that they store. The object data is stored somewhere in memory, and variables hold references to the object that tell how to find it. The variables c1 and c2 in the Counter class are examples. (In practice the reference is a memory address, but Java treats the reference abstractly and uses it to communicate with the object. Unlike C and C++, Java has no way to manipulate the memory addresses.) Method calls are messages sent to the object via the reference. This has the advantage that all references are the same size, no matter how big the object is.

However, for speed's sake there are eight primitive types that are not objects. These are:

Primitives are actually stored in the variable itself, so these primitives have different lengths in memory. This means that there are two kinds of Java variables. If a variable is of a primitive type, the variable contains the actual data itself (the bit pattern representing the data). If a variable is of type reference to an object, then it contains a reference, and the data itself is stored elsewhere.

Why is this distinction important? My wife and I have a joint checking account. We each have an ATM card. The cards are different and have different names on them, but the refer to the same checking account. If I withdraw money with my ATM card, there is less money in the account, and if my wife then looks at the balance it will be smaller even though she did nothing with her ATM card.

In this analogy, the account is the object (and bank account objects are a common example in textbooks). The ATM cards are the variables, each holding a reference to the same account. Any changes made by either of us to the account via our ATM card are seen by both. On the other hand, if my wife has her ATM card re-programmed so that it refers to her personal account (changes the reference stored in the variable), that won't affect my card or the account. She just will no longer be able to use that ATM card to withdraw money from our account, because it no longer refers to our account.

Some tricky details:

Java Classes

You have played with classes in Python (or Java), so I won't go over a lot of details. I will instead walk you through a specific example of a class, and will mention things as I go. Read the book for more details!

One important thing to remember: In Java, a class is a template or blueprint. An object is a thing created from the blueprint, usually by calling new.

Although Java does not explicitly require us to, we observe various conventions for capitalization styles of various types of identifiers.

The class that we will look at is Counter, which we skimmed over earlier. An object of this class represents a counter that starts at 0. Each time the method tick() is called, one is added to the counter. When the counter reaches a pre-defined limit it "wraps," going back to 0. Such an object could be used as part of a digital timer or digital clock class. The code for this class is here: Counter.java.

Things to note about the code: