[Oberon] Potential New Approach to Implement Instance-Centered OOP in Oberon-07
Andreas Pirklbauer
andreas_pirklbauer at yahoo.com
Mon Oct 5 05:35:14 CEST 2026
Meanwhile, through a fair amount of unexpected private communication—thank you—a few additional comments/critiques have emerged:
1. Allowing one to write something along the lines of NEW(obj, copy, CopyLine, draw, DrawLine, ...) or NEW(obj, copy := CopyLine, draw := DrawLine, ...) amounts to little more than syntactic sugar for assignments to procedure variable fields. The only additional functionality it really provides is compiler-enforced initialization.
2. There are now two constructs which are essentially the same: ordinary procedure variable fields and procedures declared in the BEGIN section. Is the intention to keep both? Why not simply provide compiler-enforced complete initialization of the former? Have you considered working with forward-declared procedures? Also, is the intention to make the BEGIN procedure variable bindings immutable? If the answer is yes, then the proposal is no longer quite equivalent to ordinary procedure variable fields, and one needs to explain why that special immutability cannot instead be attached to ordinary procedure variable fields through the type system. If the answer is no, the BEGIN construct appears to add essentially no expressive power beyond ordinary procedure variables plus mandatory initialization.
3. The proposed construct seems to suggest that it applies only to records allocated in free memory. But what about global or local variables of record types? One can of course also make the mechanism available for those. However, an assignment such as r := rExt does not change the dynamic type of r if r is a variable of record type. Polymorphism is primarily useful for constructing heterogeneous dynamic data structures, where a pointer variable can refer to objects of different extension types.
Taken together, these points suggest that the seemingly simple addition of instance-specific procedure bindings raises rather more language-design questions than might initially appear.
On Mon, Oct 5, 2026 at 03:49:59 AM Chris Burrows <cfbsoftware at gmail.com> wrote:
> I put your proposal to ChatGPT for analysis and the reply was generally favourable:
>
> https://chatgpt.com/s/t_6ac300bdf27c8191b3c26edf69adef88
>
> On 03.10.2026, at 11:48, Andreas Pirklbauer <andreas_pirklbauer at yahoo.com> wrote:
>
> The Oberon-2 programming language offers a convenient notation for object-oriented programming (OOP), namely that of type-bound procedures. It is valuable in education. However, Oberon-2 uses a class-centered view rather than an instance-centered view, meaning that Oberon-2-style type-bound procedures (methods) can essentially be viewed as constants: the same procedure is bound to all instances of a type. This reflects the reality that, in most typical applications, the same procedure (handler) is indeed bound to all instances of a class.
>
> One advantage of this approach is that a programmer cannot accidentally forget to initialize the method bindings. A disadvantage is that the bindings are fixed at the type level. This makes a new feature necessary, namely method overriding. This in turn complicates the language and the compiler and, in fact, the conceptual model. See an earlier discussion of this topic, “Class Methods vs. Procedure Variables in Records,” on this mailing list in 2017.
>
> The Graphics module provides an example where the alternative view, namely the instance-centered view, is implemented “manually”. This is done by declaring a method record and initializing its method fields manually in the module initialization body. This is somewhat cumbersome and requires some discipline from the programmer.
>
> This raises the question whether one could combine the two approaches with the following new construct:
>
>
> Part A: Replace ObjectDesc and MethodDesc
> -------
>
> Instead of the following declaration (see Graphics.Mod)
>
> TYPE
> ObjectDesc* = RECORD
> x*, y*, w*, h*: INTEGER;
> col*: BYTE;
> selected*, marked*: BOOLEAN;
> do*: Method; (*<---*)
> next: Object
> END ;
>
> MethodDesc* = RECORD
> new: Modules.Command; (*<---*)
> copy: PROCEDURE (from, to: Object);
> draw: PROCEDURE (obj: Object; VAR msg: Msg);
> change: PROCEDURE (obj: Object; VAR msg: Msg);
> selectable: PROCEDURE (obj: Object; x, y: INTEGER): BOOLEAN;
> ...
> END ;
>
> use:
>
> TYPE
> ObjectDesc* = RECORD (*<-- no more “do” field*)
> x*, y*, w*, h*: INTEGER;
> col*: BYTE;
> selected*, marked*: BOOLEAN;
> next: Object
> BEGIN (*signatures*)
> copy: PROCEDURE (from, to: Object);
> draw: PROCEDURE (obj: Object; VAR msg: Msg);
> change: PROCEDURE (obj: Object; VAR msg: Msg);
> selectable: PROCEDURE (obj: Object; x, y: INTEGER): BOOLEAN;
> ...
> END;
>
> The BEGIN section declares the operations supported by the record type, including their signatures. These are not ordinary record fields; they define the dispatch interface of the type. They effectively are forward declarations (a small drawback, as the compiler now has to check the equality of the signatures)
>
>
> Part B: Extend the intrinsic procedure NEW such that it essentially becomes a constructor
> -------
>
> NEW(obj,
> copy, CopyLine,
> draw, DrawLine,
> change, ChangeLine,
> selectable, LineSelectable,
> …);
>
> The compiler would require NEW to provide an implementation for every operation declared in the BEGIN section. We use the keyword BEGIN deliberately to suggest that, very much like the BEGIN section of a module, it is used to initialize the various fields of an instance. In this case, the initialization is performed by NEW, and it is enforced by the compiler.
>
> This approach would essentially implement the same functionality as the original Graphics module—i.e. an instance-centered view—but without much of its boilerplate code and without the risk of accidentally forgetting to initialize the various method fields. Since the bindings are instance-specific, no overriding mechanism is necessary.
>
> It seems that this could provide an elegant way of implementing OOP without introducing any new language keywords. The implementation would of course be much simpler than type-bound procedures.
>
> Has anyone seen or done experiments in this direction?
>
>
>
More information about the Oberon
mailing list