But this post isn’t about prototypes, it’s about something the Self folks
mention in passing:

In BETA, virtual functions are invoked from least specific to most specific,
with the keyword inner being used to invoke the next more specific method.
This mechanism is a product of the philosophy in BETA that subclasses should
be behavioral extensions to their superclasses and therefore specialize the
behavior of their superclasses at well-defined points (i.e. at calls to inner).

It took me a while to tease out what this is saying, but once I did, it was
like a dim little light bulb flickered on in my head.

What’s BETA?

Before I get into the lightbulb part, a bit of history. BETA is a language
that came out of the “Scandinavian School” in Denmark, the same people that
brought you Simula and kicked off the object-oriented revolution. Alan Kay
may have coined “object-oriented programming”, but it was Simula that gave him
the idea. Chances are, the language you should be coding in right now instead
of slacking off reading my blog was directly inspired by these guys.

So after Simula, they went off and made BETA. I think this is more or less
equivalent to “famous rock band goes into hiding for ten years and emerges with
avant garde free jazz album”. BETA was used as a teaching language, I think,
and there were some papers about it, but I don’t know if many people seriously
used it in anger.

(Trivia time! Some of the guys who made V8, the famously-fast JavaScript
engine in Chrome did use BETA. “V8” got its name because it’s the eighth
virtual machine that Lars Bak created. His first VM? A BETA one.)

Part of the reason BETA didn’t flourish may have to do with terminology.
Instead of classes and methods, BETA has patterns which subsume both,
somehow, and aren’t related to other uses of the term in other languages. I
wrote that sentence, and I don’t even know what the hell that means.

The BETA book is
a bit… dense. Or maybe it’s just that the syntax is so… weird:

I pride myself on being able to grok syntax on a pretty wide variety of
languages but I’m not even sure what’s a comment there. I think if you
translated that to JavaScript, it would be something like:

Like avant garde jazz, this may be genius, but it’s so out there and
unapproachable, it’s hard to tell. Fortunately, the Self guys have deciphered
some of the mystery and left that little nugget in their paper.

Overriding and super()

Let’s cover one last bit of context before I get to the point. If you’re using
any OOP language, you’re hopefully familiar with overriding methods. Details
vary between languages, but the two main points are:

A subclass can override a method in its superclass. When you invoke the
method on an instance of the subclass, the derived method gets called first.

In the body of the overriding method, it can invoke the base class method
directly in order to chain the two methods together. In Java, you do so by
calling super.someMethod(). In C# it’s base.someMethod(). In CLOS, you use
call-next-method. You get the idea.

I’m using class terminology here, but all of the above applies equally well to
prototypal languages too, with a couple of names changed.

First, it invokes CrappyBankAccount#deposit(). Then, when that calls
super.deposit(), it chains to the base Account#deposit() method.

Who’s in Charge Here?

What this means is that the subclass is in control of the dispatch chain.
When you override a method in Java, you get to decide if you do stuff before
calling super or after. You can change the arguments you pass to it, or even
skip calling it entirely.

This is great for flexibility, but as an API designer, that can be frustrating.
When I’m making a class that’s designed to be subclassed, I often have
constraints that I want my class to ensure.

Here we’re making a game with a base class for a character in the world. It
provides a default render() method that tells the renderer where to render.
The subclass overrides it and draws the specific image that’s appropriate for
that character.

There’s an implied requirement here: if you override render() in a subclass,
you must call super.render()before you do any drawing. If you don’t, the
transform won’t be set and it’ll draw wrong.

These hidden requirements rub me the wrong way. If you’re implementing a
subclass of GameObject, how are you supposed to know that you need to do that?
You can document it, but it would be better if the base class itself made sure
you did the right thing.

render() and onRender()

To solve this, what I (and lots of other people) do is split these into two
methods, like so:

Our public render() method is now designed to not be overridden. (In C++ or
C# you’d make it non-virtual.) It does the set-up it needs and calls the
protected abstract onRender() method. That method is intended to be
overridden, and by making it protected and abstract, it’s clear you must
override it. Marking it abstract also makes it clear that you don’t need to
call super().

This lets the base class stay in control of the dispatch process. It can do
set-up before and after the subclass’s “overridden” method gets called. The
dispatch order is reversed now. When you call render(), you hit the
superclass first and then it calls onRender() in the subclass.

This is almost always how I design classes that I intend to be subclassed. It’s
rare that I override methods in my code that aren’t abstract, and I’ve been on
teams with style guides that enforced this pattern.

Back to BETA

Of course, the problem with this is that it is a pattern. You have to make a
pair of methods, and every time you have another level of subclassing, you need
a new name. (If there was a subclass of ScaryMonster that wanted to override
onRender() then ScaryMonster would have to add a onOnRender().) This
brings us back to BETA.

Overriding methods in BETA works exactly like this pattern, but baked right
into the language. Instead of calling super() in the derived class, you
call inner() in the base class. That tells it to chain down to the
subclass at that point.

When you invoke an overridden method, dispatch starts at the base class (just
like we want in the GameObject example) and then walks down to the subclasses
at the superclass’s whim. In other words, our example with BETA-style
overriding would look like:

Here, we’ve added a call to restoreState() after the call to inner(). By
giving control of the dispatch to the base class, it can execute code both
before and after the derived class code. super() doesn’t let you do that.
(Though super() does let you handle the opposite case: you can put code
before and after the base class code in the derived method that calls
super().)

It also gives you a convenient way to control which methods are virtual and
which aren’t: if a method doesn’t call inner() it implicitly can’t be
overridden since it cedes no control to a subclass.

What this means is that base classes have explicit control over how they can be
extended. Outside of programming “override” has negative connotations: it means
you’re hijacking something without its consent and indeed overriding does kind
of work like that in most languages.

In the early days of class-based OOP, people thought any old class could be
spontaneously subclassed. You could just override some stuff and it would all
magically work out. What we’ve finally realized is that the API you expose to
subclasses is another boundary layer that needs to be carefully designed.
Ad-hoc subclassing rarely works and classes generally need to be designed up
front in order to be subclassed.

BETA was designed around that model. With typical Scandinavian politeness, you
don’t override your base class, you politely request permission to extend it.
I think right now, the style of a lot of OOP code today fits that model better.

Most languages chose a different path than BETA, but this makes me wonder if
Kristen and company had it right all along.