Object-Oriented Design Principles
Fields are ordinary variables bound to class or object namespaces, scoped to their context and not global.
One Class, Two Kinds of Ownership
A class can contain fields whose ownership belongs either to the class as a whole or to each individual object. That ownership determines whether the value is shared or kept separate. Class variables are shared across all instances, while object variables belong to one particular instance. Neither kind is global: each field is bound to a class or object namespace and is scoped to that context.
Ask one question before choosing a variable type: does this data describe the class as a whole, or does it describe one individual object?
Robot State Before Any Change
The source example uses a Robot class with two fields. The class variable population records a value shared by the class. The object variable name records an individual robot's name. The placement of each field signals its ownership: population is defined at class level, while self.name is attached to the instance inside initialization.
Tracing Construction
Determine the values after robot1 and robot2 are created.
Create robot1: self.name = name creates the object variable robot1.name with the value R2D2. Robot.population is then incremented from 0 to 1.
Create robot2: A separate object variable robot2.name receives C3PO. Robot.population is incremented again, so the shared value becomes 2.
Compare ownership: The two name values are independent because each belongs to a different object. The population value is shared because it belongs to the class.
Robot.population is 2, robot1.name is R2D2, and robot2.name is C3PO.
Reading and Modifying Each Namespace
The access form reflects ownership. Use the class name for a class variable, as in Robot.population. Use the instance for an object variable, as in robot1.name. In the Robot example, creating an object gives that object its own name, but the population update changes the one shared class value.
| Question | Class variable | Object variable |
|---|---|---|
| Who owns it? | The class | An individual instance |
| How many copies? | One shared copy | One independent copy per instance |
| How is it accessed in the source example? | Robot.population | robot1.name or robot2.name |
| What happens when it changes? | All instances see the changed shared value | Only the modified instance changes |
| Typical data use | A count shared by all objects | An individual object's name or state |
Ownership determines sharing and the effect of later changes.
What Changes When a Robot Dies
What do you think happens?
After robot1.die() runs, what values should be expected for Robot.population, robot1.name, and robot2.name?
Reveal answer
Answer: Population becomes 1; robot1.name remains R2D2 and robot2.name remains C3PO.
die changes Robot.population, the shared class variable. It does not change either object's name variable.
2
R2D2
C3PO
1
R2D2
C3POThe important trace is short. robot1.die() executes Robot.population -= 1, so the shared population changes from 2 to 1. The method does not assign to self.name. Therefore robot1.name remains R2D2, and robot2.name remains C3PO. A class-variable change is visible across the class's instances, while an object-variable change would be limited to its owner.
Choosing the Right Field Type
Choose a class variable when every instance should see one shared value and changes to that value should be visible to all instances. The source uses a population count as this kind of data. Choose an object variable when every instance needs its own independent value. The source uses each robot's name as this kind of data.
Ownership Decision
For a Robot class, decide whether a field should be shared or individual: the number of robots currently tracked, and the name of each robot.
Evaluate the population count: The count describes the group of robots rather than one robot. All instances should observe the same count, so it belongs as a class variable.
Evaluate the name: Each robot can have a different name. Each instance needs its own independent value, so the name belongs as an object variable.
Check the access form: Use Robot.population for the shared count and an instance expression such as robot1.name for an individual name.
Use a class variable for shared population data and an object variable for each robot's name.
Mistakes in Ownership Tracing
Treating every field as if it were shared.
self.name creates an object variable for the individual instance, so each robot has an independent name.
Fix:
Track the object attached to self. robot1.name and robot2.name belong to different instances.Treating a class variable as if it belonged to only the object that changed it.
The method changes Robot.population, which is the shared class variable.
Fix:
Follow the class-qualified expression Robot.population and expect the shared value to change.Ignoring where the field is defined.
The source uses placement and binding to distinguish class ownership from object ownership.
Fix:
Check whether the field is defined at class level or attached to self.Using the wrong access form when tracing ownership.
The source distinguishes class access through the class name from object access through an instance.
Fix:
Use Robot.population for the class variable and robot1.name or robot2.name for object variables.
Ownership Practice
Using the Robot example, trace the state after robot1 = Robot('R2D2') and robot2 = Robot('C3PO') execute. Then trace the state after robot1.die(). For each step, record Robot.population, robot1.name, and robot2.name. Finally, label each field as a class variable or an object variable and explain why.
Hints
- Start with the class-level population value of 0.
- For each construction, trace self.name and Robot.population separately.
- When die runs, identify the exact field named in Robot.population -= 1.
- Find the owner of each field: the class or an individual instance.
- Use the access syntax as evidence: ClassName.variable or instance.variable.
- For every modification, ask whether the changed value is shared or independent.
- After each line, write the current value for the class field and each object's fields.
Key Takeaways
- A class variable belongs to the class, has one shared copy, and is visible across all instances.
- An object variable belongs to one instance, so each instance has its own independent copy.
- Class variables are accessed through the class name, while object variables are accessed through an instance.
- Changing a class variable changes the shared value observed by all instances; changing an object variable affects only its owner.
- Choose the variable type by asking whether the data describes the class as a whole or an individual object.
Key Takeaways
- Class variables are shared by all instances, while object variables are unique to each instance.
- The owner of a field determines whether a change is shared or independent.
- Robot.population demonstrates shared class data, while self.name demonstrates per-object data.
- Trace the field's definition, access form, and modification to predict program state.
- Use class variables for data shared by the class and object variables for data that differs between instances.