[Oberon] Protocols (interfaces) in Oberon-2

Charles Perkins chuck at kuracali.com
Mon Oct 26 15:37:21 CET 2020


Hi Jörg,

With this example I think I understand how Oberon can in fact already do
what I want in composing Interfaces. In Wirthian fashion the mechanism is
explicit rather than implicit. I had not made the mental jump to how a
record may be based on more than one base record... with that, everything
else falls into place.

I observe that this means that interfaces are 'opt in' rather than
automatic based on just matching a subset of method names, but that's
typical and arguably more safe anyway.

I'm going to think on this some more.

Thank you very much for taking the time to illustrate this to us.

Best,
Chuck


On Sun, Oct 25, 2020 at 11:55 PM Jörg <joerg.straube at iaeth.ch> wrote:

> Chuck
>
>         > Andreas, in your scheme can you create separate protocols, for
> example
>         > "Jsonify" with the method ToJSON and a different protocol
> "Persistify" with
>         > the methods "Store" and "Load", and have other records implement
> one or the
>         > other or neither or both?
>
> Here my proposal for doing this in standard Oberon-07.
> In the previous mail, I separated interface/protocol and implementation
> for clarity. The same should be done here. For brevity, I combined the two
> here.
>
> MODULE Data;
> (* Definition of whatever your internal data structure looks like. Here
> just an example *)
> TYPE
>   Tree* = POINTER TO TreeDesc;
>   TreeDesc* = RECORD val*: ARRAY 15 OF CHAR; left*, right*: Tree END
> END Data.
>
> MODULE Jsonify;
> IMPORT Data;
> TYPE
>   Methods* = POINTER TO MDesc;
>   MDesc* = RECORD
>     toJSON: PROCEDURE(this: Data.Tree);
>   END;
>   (* empty or default implementation *)
>   PROCEDURE J(this: Data.Tree); END J;
>   PROCEDURE New*(VAR m: Method); BEGIN NEW(m); m.toJSON := J END;
> END Jsonify.
>
> MODULE Persistify;
> IMPORT Data;
> TYPE
>   Methods* = POINTER TO MDesc;
>   MDesc* = RECORD
>     Load: PROCEDURE(VAR this: Data.Tree);
>     Store: PROCEDURE(this: Data.Tree)
>   END;
>   (* empty or default implementation *)
>   PROCEDURE L(VAR this: Data.Tree); BEGIN this := NIL END L;
>   PROCEDURE S(this: Data.Tree); END S;
>   PROCEDURE New*(VAR m: Methods); BEGIN NEW(m); m.Load := L; m.Store := S
> END Init;
> END Persistify.
>
> Here now a module using both interfaces/protocols and overwrite even one
> persist procedure with an own version, if wanted.
> MODULE Usage;
> IMPORT Data, Jsonify, Persistify;
> TYPE
>   User = RECORD (Data.Tree)
>     j: Jsonify;
>     p: Persistify
>   END;
> VAR u: User;
> PROCEDURE myLoad(this: Data.Tree); (* implement your version of persist
> Load *) END myLoad;
> PROCEDURE New*(VAR u: User);
>   BEGIN NEW(u); Jsonify.New(u.j); Persistify.New(u.p); u.p.Load := myLoad
> END New;
>
> BEGIN
>   New(u); u.j.toJSON(u); u.p.Load(u) (* this calls my version *)
> END Usage.
>
> Adding the qualifiers "j" and "p" circumvents the ambiguity in case the
> two interfaces defined methods with the same name.
>
> br
> Jörg
>
>
>
> --
> Oberon at lists.inf.ethz.ch mailing list for ETH Oberon and related systems
> https://lists.inf.ethz.ch/mailman/listinfo/oberon
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.inf.ethz.ch/pipermail/oberon/attachments/20201026/402b0907/attachment.html>


More information about the Oberon mailing list