Back to the home page.

Thoughts on an Object Model

Programs are built by combining abstractions. The Mozart project calles them "tones" and the Intentional Programming project calls them "intentions." All programming languages provide a set of abstractions, and all serious languages provide limited mechanisms to define new abstractions.

An Object-Oriented Approach

In object-oriented terms, an abstraction is similar to a class in the sense that it is a pattern from which instances are created; altough a program may have many "for" loops (the instances), the language provides a single notion of what a "for" loop is (the class).

There is an important difference between abstractions and classes because some instances are themselves classes. For instance, there is the abstraction of function definition whose instances are functions. Functions are themselves abstractions whose instances are function calls.

This unity between classes and instances can be found in some object-oriented languages, notably Self, CLOS, and Cecil. In these languages, each object is its own class, and there is no distinction between instantiation and subclassing. The relationship between abstractions and their instances is clearly not to same as these languages' relationship between objects and their derived objects; if it were, a function call would be a kind of function definition!

A better analogy may be in Java inner classes. In this view, an abstraction is an instance of a class that contains an inner class. The inner class is that class of the abstraction's instances. By the semantics of inner classes, each instance will have an implicit link to the abstraction that created it. The function defininition/function/function call classes would look something like this:

  public class FunctionDef {
    public class Function {
      public class FunctionCall {
        public FunctionCall(...) {...}
        public Function abstraction() { return Function.this; }

      public Function(...) {...}
      public FunctionCall instance(...) { return new FunctionCall(...); }
      public FunctionDef abstraction() { return FunctionDef.this; }

    public Function instance(...) { return new Function(...); }

A Functional Approach

Maybe an object-oriented approach is not the best. Object-oriented systems focus on creating opaque objects manipulated only through their methods. This seems to be a wrong approach for representing abstractions, which are fundamentally transparent.

Transparent or Opaque?

Should the representation of an abstraction be transparent or opaque?

Abstractions in Existing Languages

Consider, for example, C. The built-in abstractions include variables, control flow constructs, and arithmetic. There are also meta-abstractions, such as functions, structs, and macros, each of which allows the user to define new abstractions.

While the built-in abstractions have distinctive syntax consisting of reserved words and punctuation, the user-defined abstractions have a sort of cookie-cutter syntax; the syntax for a function abstraction is the function's name followed by a pair of parentheses, usually with some arguments between the parentheses.

Likewise, user-defined abstractions have cookie-cutter semantics. For instance, function calls evaulate each of their arguments before executing the function's body. By contrast, built-in abstractions show a wide variety of behaviors when dealing with their arguments. Arithmetic operators evaluate their arguments once, just like functions, but loops evaluate their arguments many times, logical operators ("&&" and "||") may only evaluate one of their arguments, and the "sizeof" operator never evaluates its argument!

Last update: $Date: 2002/09/10 15:57:54 $