In this system, an object is simply a pointer to some memory (where instance data can be stored), preceded by a pointer to a 'vtable'; i.e. `myObject` is a pointer to some memory, and `myObject[-1]` is a pointer to a vtable.
Vtables are themselves objects, implemented in the same way as above. There is a "vtable API" defining methods that a vtable should support, and a default 'vtable vtable' is defined during a bootstrap step (which is its own vtable).
The resulting object system has objects which are completely opaque: they're just arbitrary chunks of memory, which are only useful to the methods defined by their associated vtable. Since those vtables are also opaque objects, we can provide our own objects which implement the idea of 'method call' in whichever way we like.
So you've got components that cannot talk to each other, because the available methods differ (not just by name, but by what you can actually do), even though they are working on the same conceptual thing.
The article argues for more "base datatypes" that are in common use. It doesn't matter whether the language/runtime exposes them as objects or PODs.
Whereas in an Object Oriented language you would access the elements by calling a method myArray.at(123). The benefit is you don't need to know how that data is stored or where.
In OOP the elements of an Array of course can be Arrays too, whose elements you can similarly only access via a method-call.
OOP is only an attractive and helpful conceptualization of doing something with a data representation in a computer's memory, not a magical way to suppress differences. It doesn't help with incompatible representations, operations and expectations about them except by providing some tools to deal with problems.
On a more formal side, as already noted in other comments, if everything is an Object everything is nothing more than an Object: a one-type programming language is certainly coherent but no good if one wants to write meaningful programs.
The "formal side" assumes a static environment, but our OS and apps and browsers are constantly churning. When the runtime reality diverges from the compile-time model, you'll want dynamicism: can this object do that? What happens if I try to invoke an unsupported operation? etc.
Also, the message does not need to be called "join," especially since it's use in the culture is ambiguous and confusing.
In Smalltalk even the 'nil' meaning no object at all is an Object.
At which point you may decide you just want to represent altitude with reference = "same as everywhere else in the program, because if it's the same, it doesn't matter what it is". Which is what most non-GIS code does, except it isn't documented explicitly, and it's up to the user or integrator to ensure the data fed to the program uses the same reference as the user expects to see.
I think it was in one Smalltalk book: so there are objects that send messages to each other, but how things are really done in Smalltalk? :) At some points there are primitive actions that actually do the work. Similarly with data we can define objects or any other higher-level concepts, but somewhere there must be actual data under all these abstractions.
[1] http://stephane.ducasse.free.fr/FreeBooks/BlueBook/Bluebook....