Hero image for "Self Asked What Happens When You Delete the Class Keyword Entirely"

Self Asked What Happens When You Delete the Class Keyword Entirely


Picture the Java tutorial example almost every programmer has seen: Animal is the base class, Dog, Cat, and Cow extend it, and each overrides sound() to bark, meow, or moo (GeeksforGeeks). It's a clean diagram. It's also a commitment. Before you've written a single Dog object, you've had to decide what a Dog is, carve out its place in a hierarchy, and hope the hierarchy still makes sense five years and fifty new animal types later. Self, built by David Ungar and Randall Smith between 1985 and 1995, was an argument that this commitment was never necessary in the first place (Wikipedia).

Objects Without a Blueprint

Self didn't invent the idea of skipping classes — that lineage runs back further than most people assume. Bobrow and Winograd's KRL, a 1976 Stanford project, was already using "prototype" in roughly its modern sense and had implemented multiple inheritance of properties between objects. MIT's Actors group, working on ACT-1 in 1979, built something similar but called the underlying mechanism "delegation" specifically to distinguish it from class-based inheritance. Alan Borning's 1981 paper in ACM Transactions on Programming Languages and Systems is credited with popularizing the term "prototype" itself (Wikipedia).

What Self did was take that lineage and make it the thing academics actually talked about. It's described as the language that made prototypes a known, discussed concept in programming language circles, even though it wasn't first and wasn't what eventually made prototypes ubiquitous in everyday code — that distinction goes to JavaScript (Wikipedia). Self's contribution was conceptual clarity: here is a style of object-oriented programming — sometimes called classless or instance-based — where you don't define a type and then stamp out instances of it. You take an object that already exists, clone it, and modify the clone. A "banana" isn't an instance of a Banana class inheriting from Fruit. It's a copy of a generic banana object, with its own tweaks layered on top.

The Class Hierarchy Was Always a Prediction

The reason this matters isn't nostalgia for an obscure research language. It's that class-based inheritance asks you to predict structure in advance, and predictions age badly. Python's own documentation on inheritance versus composition spends considerable space on what it calls "the class explosion problem" — the way hierarchies multiply combinations of behavior until you're drowning in subclasses that each capture one narrow variation (Real Python). Java's standard teaching materials show the same shape in miniature: Animal branching into Dog, Cat, Cow, each needing its own subclass just to override one method (GeeksforGeeks). The hierarchy is doing organizational work before you know what organization you'll actually need.

Self's cloning model sidesteps the prediction problem by refusing to separate the "type" question from the "instance" question. There's no abstract Fruit you have to define correctly up front. There's just a fruit-like object sitting around, and if you need a banana, you copy it and append what's different. Inheritance stops being an architectural decision made at design time and becomes something closer to an editing decision made at the moment you need a new variant.

The Idea Outlived the Language

Self itself didn't take over the industry — it's remembered more as an influence than a workhorse. But the model it crystallized became inescapable through a much more famous descendant. JavaScript's object system still runs on the same basic mechanism: objects link to other objects through a prototype chain, and property lookups walk that chain until they find what they're looking for (Medium/JsPoint). Every time a JavaScript developer complains that this behaves strangely, or discovers that modifying an object's prototype changes every object linked to it, they're bumping into decisions that trace straight back to the classless experiment Self ran in the late 1980s.

What's worth sitting with is how differently the two camps have aged. Class-based languages responded to the explosion problem not by abandoning classes but by adding escape hatches — composition, mixins, interfaces — bolted alongside the hierarchy rather than replacing it (Real Python). Self's answer was structural: if the hierarchy is the source of the rigidity, remove the hierarchy. JavaScript inherited that answer by accident of history rather than philosophical commitment, which is maybe why so many JavaScript developers spend years using prototypes without knowing they're standing on an argument someone made deliberately, decades earlier, about what an object even needs to be.