Object-oriented programming began as a programming paradigm to support the creation of computer-based simulations of real-world objects. Classes were used to define different kinds of real-world objects (e.g., wolves and sheep), with objects being created (or “instantiated”) to represent distinct actors in the simulation (e.g., “wolf number 42” or “sheep number 17”). The class specified the data that was needed to represent an object of that class (e.g., the hunger level of a wolf or the meat content of a sheep) as well as the operations that could operate on the object (e.g., change the hunger level). Encapsulating state information with the functions that operate on that state information turned out to be a useful programming technique, even when classes represent abstract entities and not just real world ones. The abstraction and interfaces provided by object-oriented programming allow large teams of programmers to work independently yet share code in a reliable way.
Beginning programmers working on small problems may have little need to create new classes, but they will often use existing classes in solving problems, so it is helpful to understand object-oriented concepts.
Analogies
Sometimes students have trouble distinguishing between the concept of a class and an object. An analogy to help them understand the difference is to describe a class as being like a blueprint for a house. The blueprint describes the overall design, appearance, and components of a house. Houses, on the other hand, are “instances” of the blueprint. They are like the objects created from classes in an object-oriented system. Each house has specific information that distinguishes one from the other (e.g., colors, roof type, and door locks), but the overall structure is the same.
Implementation
When an object is created, a block of storage in main memory is allocated to hold the variables that are unique to each instance. These variables are called “data attributes” in Python and “member variables” or “fields” in Java. A pointer or reference to this block of storage is then typically stored in a variable for later reference. The fields and methods in the object are referenced using “dot notation”, e.g., x.y or x.f().
Understanding that the storage of an object is separate from the variable that references it is important for understanding how objects are passed as parameters to functions. Passing an object as a parameter means passing a reference or pointer to that object. Changing one of the data attributes of the object inside the function changes the same data attribute seen by the caller of the function (since there is only one object, not a copy).
In Python, the implementation of data attributes is more general than the implementation of member variables in Java. In Python, the variables of an object are stored in a dictionary, permitting new variables to be created (or deleted) at runtime. In Java, the variables must be declared at compile time and are fixed for the life of the program.
These concepts and others are explained in more detail in the examples section.