Objects, classes & interfaces
Every pattern on this site is a sentence written in one language: objects, interfaces, inheritance, composition. If that vocabulary is fuzzy, the patterns read like magic incantations - memorable, but unusable. Ten minutes here saves you the rest of the site.
Objects and classes
A class is a blueprint. An object is a thing built from it. The class says every cat has a name, a sex, an age and a color, and that every cat can breathe, sleep, run and meow. Your cat Oscar fills in the values.
Fields and methods together are the class's members. The data currently sitting in an object's fields is its state; what its methods let it do is its behavior. Oscar and your neighbor's Luna are the same class and completely different objects, because state is per-object and behavior is per-class.
Anatomy of a UML class box: one name, one block of state, one block of behavior.
Objects are instances of a class: same fields, different state.
Try it yourself: sketch a Car class instead of Cat - three fields and two methods
it would need. Then imagine two Car objects side by side. What is different between
them, and what is identical because it lives on the class rather than the object?
Enums
A class restricted to a fixed, named set of instances, decided once at compile time.
Instead of passing the string "PENDING" around and misspelling it in one call site out
of forty, you declare OrderStatus.PENDING and the compiler refuses to let anything else
exist under that name.
Under the hood, an enum is still a class - the compiler just pre-builds exactly one object per named value and seals the constructor. That is why an enum constant can carry its own fields and override its own methods, the same as any other object:
Two things this buys you that a raw constant cannot: the compiler rejects an
out-of-range value at the call site instead of at 3 a.m. in production, and a switch
over an enum can be checked for exhaustiveness, so adding RETURNED later surfaces every
place that forgot about it. The price is symmetrical - adding a value means touching the
enum's own declaration, which is exactly the kind of "vary here" instability the
State pattern exists to route through polymorphism instead, once the per-constant
behavior outgrows a switch.
Try it yourself: sketch an enum for a traffic light - RED, YELLOW, GREEN.
Which method would you want each constant to override so its behavior differs per
value, the way refundRate() differs per OrderStatus?
Interfaces
A contract with no implementation attached: a list of method signatures a class promises to honor, and nothing about how it honors them. A class describes what an object is. An interface describes what an object can do.
A checkout flow that holds a PaymentMethod reference never learns whether it is
charging a card, debiting a wallet or moving a coin. Ship Apple Pay next year and the
checkout code does not change - one more class keeps the same promise, and nothing that
already worked notices the addition.
Interface vs abstract class
Both let you program to an abstraction, and both show up constantly in machine-coding interviews, which is exactly why the distinction gets asked about directly. The line:
- Interface - a pure contract. No fields, no method bodies, no state. A class can implement as many interfaces as it likes, because promising to do several unrelated things costs nothing until you actually implement them.
- Abstract class - part contract, part implementation. It can hold state and finished methods alongside the abstract ones subclasses must fill in. A class can extend exactly one, because it is inheriting real, concrete code, not just a signature.
Reach for an interface when unrelated classes need to promise the same behavior and
nothing else - a Bird and an Airplane share zero code but can both promise fly().
Reach for an abstract class when subclasses genuinely share implementation and only differ
in specific, well-defined places - that shared code is the entire reason to inherit.
An abstract class earns its keep the moment two subclasses would otherwise duplicate the
same finished method. SalariedEmployee and HourlyEmployee both need to clockIn() and
clockOut() in an identical way; only calculatePay() actually differs between them.
That mix - some methods finished, one left as a promise - is exactly what an interface cannot offer, since an interface cannot finish any method at all.
Try it yourself: Shape needs Circle, Square and Triangle to all expose
area(), sharing zero implementation. Separately, Employee needs SalariedEmployee
and HourlyEmployee to share clockIn()/clockOut() but calculate pay differently.
Which one gets an interface and which gets an abstract class, and why?
Class hierarchies
Once you notice dogs also have a name, a sex, an age and a color, and also breathe and
sleep, the shared parts want a home. That home is a base class - Animal - with Cat and
Dog extending it and contributing only their differences: meow() here, bark() there.
Animal hierarchy.The parent is the superclass, the children are subclasses, and subclasses can
override inherited methods either to replace the default behavior or to extend it. Push the
idea one level up and Animal and Plant both descend from Organism. A Cat then
inherits from everything above it. That stack is a hierarchy, and it is useful right up
until the moment it is not - see Class relationships and Design principles for what
replaces it once a hierarchy tries to model more than one dimension of variation.
Try it yourself: extend the Organism tree with a Fungus branch that shares
almost nothing with Animal or Plant except being alive. At what point does forcing
it under Organism start to feel like the wrong tool, and what would you reach for
instead?
Check yourself
Oscar and Luna are both Cat objects. What is different between them, and what is shared?