Skip to content

Chapter 3 of 8

Classes, Objects, and Language Mechanics

At the heart of OOP lies the distinction between a class and an object, and the related idea of object identity versus equality. A class is a blueprint or template that defines attributes and behaviors, while an object is a concrete instance of that class created at runtime. The analogy of an architectural plan versus an actual building captures the relationship well: many distinct buildings can be constructed from the same plan, just as many objects can be instantiated from a single class. In Java, the expression Car myCar = new Car(); creates a new object from the Car class definition. Closely related is the distinction between identity, where two references point to the same object in memory (a == b in Java or a is b in Python), and equality, where two distinct objects share the same value or state (a.equals(b) in Java or a == b in Python). When overriding equals in Java, hashCode must be overridden too, since equal objects must share a hash code even though identical hash codes do not imply equality.

Constructors are special methods invoked automatically when an object is created, responsible for initializing the object's state. They share the class name, have no return type, and can be overloaded with different parameter lists to provide multiple ways of constructing an object. If no constructor is defined, most languages provide a default constructor. The expression new Car("Toyota", 2024) invokes a constructor that accepts those arguments and sets up the new object accordingly. Destructors play the symmetric role on the other end of an object's life, releasing resources like file handles, memory, or network connections. In C++, a destructor declared with a tilde runs deterministically when an object goes out of scope, while Python uses __del__ invoked by the garbage collector, and Java relies on try-with-resources and AutoCloseable rather than true destructors.

Access modifiers control the visibility of class members and play a key role in enforcing encapsulation. The public modifier allows access from anywhere, private restricts access to within the declaring class only, and protected allows access within the class and its subclasses. Java also offers package-private visibility, the default when no modifier is specified, which restricts access to the same package. A common best practice is to default to private and widen access to protected only when subclasses genuinely need to access or override the member. The final keyword provides a complementary way to enforce immutability and communicate design intent: a final class cannot be subclassed (as with Java's String), a final method cannot be overridden, and a final variable cannot be reassigned after initialization. Using final thoughtfully can also help avoid the fragile base class problem by signaling which parts of a class are not designed for extension.

Static and instance members differ in how they belong to a program. Static members belong to the class itself, are shared across all instances, and are accessed via the class name such as Math.PI. They cannot access instance variables because they exist independently of any particular object. Instance members, by contrast, belong to each object individually, are accessed through an object reference like dog.name, and can freely access both static and instance members. Static methods work well for utility functions like Math.max, factory methods like List.of, or any logic that does not depend on instance state, but they should be avoided when polymorphic behavior is required or when they would create tight coupling.

All chapters
  1. 1The Four Pillars of OOP
  2. 2The SOLID Design Principles
  3. 3Classes, Objects, and Language Mechanics
  4. 4Object Relationships
  5. 5Polymorphism and Method Dispatch
  6. 6Abstraction Through Interfaces and Abstract Classes
  7. 7Composition, Inheritance, and Code Reuse
  8. 8General Software Design Principles

Drill it

Reading is not remembering. These come from the Oop Principles deck:

Q

What is encapsulation in OOP?

Encapsulation is the bundling of data and methods that operate on that data into a single unit (class), while restricting direct access to some components.Key b...

Q

What is inheritance in OOP?

Inheritance allows a child class (subclass) to acquire the properties and behaviors of a parent class (superclass).Example in Java:class Dog extends Animal { }B...

Q

What is polymorphism in OOP?

Polymorphism means "many forms" — the ability of an object to take on different behaviors depending on its type.Two main types:Compile-time (static): method ove...

Q

What is abstraction in OOP?

Abstraction is the process of hiding complex implementation details and exposing only the essential features of an object.Achieved through:Abstract classes — pa...