The central idea of traditional object-orientation is that everything is a function. The thing we can do with a function is apply it to an argument. We cannot inspect it, look into how it was constructed. Only apply.
In a traditional object-oriented language, the argument a function is applied to is a selector-and-arguments-tuple.
E.g. some Smalltalk:
That is:
3
applied to the selector +
and a list of arguments containing 2
.5
applied to the selector negated
and the empty list of arguments.3
applied to the selector to:by:
and a list of arguments containing 10
and 2
.There are details and there is often some cheating and pragmatism going on somewhere. But the idea is that everything is a function and we cannot “look inside” a function.
A number is a function that behaves and responds appropriately when applied to an argument. We do not care how the number is constructed. More precisely, we cannot care how the number is constructed.
If a function walks like a number and it quacks like a number, then it must be a number.
―Alonzo Church
(Contrast with more data-oriented languages like those in the extended ML family. Here we tend to define numbers by how they are constructed. “A natural number is zero or the successor of a natural number.” And when operating on a number we look into how it was constructed and do case analysis (typically by using pattern matching). “If it is zero, then such and such, if it is the successor of something, then this other thing instead.”)