12.3 Classes, Objects, Instance Variables, Methods, and Encapsulation
Key Takeaways
- A class defines the instance variables (data) and methods (behavior) shared by all its objects; each object created with new has its own values for the instance variables.
- In a UML class diagram, the top box is the class name, the middle box lists instance variables, and the bottom box lists methods; − means private and + means public.
- Encapsulation makes instance variables private and provides public methods, so every change to an object's data passes through code that can validate it.
- Benefits of encapsulation include protecting data integrity, hiding implementation details, and allowing internal changes without breaking code that uses the class.
- A constructor initializes a new object's instance variables when the object is created.
What this competency asks
Under object-oriented programming, ETS asks you to:
- Identify classes, instance variables, and methods given a diagram.
- Identify the benefits of inheritance and encapsulation (inheritance is covered in Section 12.4).
- Identify distinctions between overloading and overriding (Section 12.4).
The ETS notation includes class className … end class className and the keywords extends, new, public, and private.
Classes and objects
A class is a blueprint. An object (instance) is one concrete thing built from it.
class Counter
private int count // instance variable
public Counter ( ) // constructor
count ← 0
end Counter
public void increment ( ) // method
count ← count + 1
end increment
public int getCount ( ) // method
return count
end getCount
end class Counter
(ETS's notation table does not show a constructor. The form above, a method named like the class, is the common Java-style convention.)
Counter a ← new Counter ( )
Counter b ← new Counter ( )
a.increment ( )
a.increment ( )
b.increment ( )
print a.getCount ( ) + " " + b.getCount ( )
Output: 2 1. Each object has its own count, so incrementing a does not affect b.
| Term | Meaning | In Counter |
|---|---|---|
| Class | Blueprint for a type of object | Counter |
| Object / instance | One thing created from the class with new | a, b |
| Instance variable (field, attribute) | Data stored in each object | count |
| Method | Procedure that belongs to the class and works on an object's data | increment, getCount |
| Constructor | Runs when an object is created; sets initial values | Counter ( ) |
| State | The current values of an object's instance variables | a's count is 2 |
| Behavior | What the object's methods can do | Increase and report the count |
A method is called on a specific object with dot notation: a.increment ( ) changes a's count and nobody else's.
Class (static) members
Some languages also let a variable or method belong to the class itself rather than to each object. Java marks these static. One copy is shared by all objects, for example a counter of how many objects have been created, or a utility method such as Math.sqrt. They are not in ETS's keyword list, but you will meet them in Java.
Reading a class diagram
UML class diagrams show a class as a box with three compartments.
| Compartment | Contents | Example for Book |
|---|---|---|
| Top | Class name | Book |
| Middle | Instance variables, as name : type | − title : String, − pages : int |
| Bottom | Methods, as name(parameters) : return type | + getTitle ( ) : String, + read ( n : int ) : void |
Symbols: − private, + public, # protected (visible to subclasses). An arrow with a hollow triangle points from a subclass to its superclass (inheritance; Section 12.4).
When a question asks you to "identify the instance variables," list the middle compartment. For the methods, list the bottom compartment. The class name is the top. Parameters listed inside a method, such as n in read ( n : int ), are not instance variables.
Encapsulation
Encapsulation bundles an object's data with the methods that use it and restricts direct access to the data. Instance variables are private, and access goes through public methods.
class BankAccount
private double balance
public double getBalance ( ) // accessor ("getter")
return balance
end getBalance
public boolean withdraw ( double amount ) // mutator with validation
if ( ( amount > 0 ) and ( amount ≤ balance ) )
balance ← balance - amount
return true
end if
return false
end withdraw
end class BankAccount
If balance were public, any code could write acct.balance ← -50000. Because it is private, the only way to reduce the balance is withdraw, which refuses invalid amounts.
Benefits of encapsulation
| Benefit | Explanation |
|---|---|
| Data integrity | Every change passes through methods that enforce the rules (the class invariants), such as "balance is never negative" |
| Information hiding | Users of the class see what it does, not how, which is abstraction |
| Easier change | The internal representation can change, for example storing cents in an int instead of dollars in a double, without changing code that calls the public methods |
| Easier debugging | If a value is wrong, only the class's own methods could have changed it |
| Clear interface | The public methods document how the class is meant to be used |
Access levels
| Modifier | Accessible from |
|---|---|
private | Only code inside the same class |
public | Any code |
protected (Java, C++) | The class and its subclasses (in Java, also classes in the same package) |
ETS's pseudocode lists only public and private.
Designing a simple class
To model a real entity, ask:
- What does each object need to remember? Those become the instance variables, usually
private. - What should an object be able to do, or report? Those become the public methods.
- What must always be true? Enforce it in the constructor and the mutators.
For a Student: instance variables name, id, and gpa; methods getName ( ), updateGpa ( newGpa ) (which rejects values outside 0.0–4.0), and toString ( ).
A class diagram for Book lists − title : String and − pages : int in its middle compartment, and + getTitle ( ) : String and + read ( n : int ) : void in its bottom compartment. Which are the instance variables of Book?
A Thermostat class declares public int targetTemp. Other code sometimes sets targetTemp to 500, which breaks the heating system. Which change best applies encapsulation?
What is printed?
(Each new Counter starts with count 0, increment adds 1 to that object's count, and getCount returns it.)Counter a ← new Counter ( )
Counter b ← new Counter ( )
a.increment ( )
a.increment ( )
b.increment ( )
print a.getCount ( ) + " " + b.getCount ( )