[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Abstract classes in Oberon / OOC
At 11:44 AM 15/12/98 -0500, you wrote:
>Michael van Acken <Michael.van.Acken@de.uu.net> writes:
>> Stewart Greenhill <greenhil@murdoch.edu.au> writes:
>> > Would it be possible to add something like this to OOC? Here are two
>> > possibilities:
>> >
>> > 1) Allow [ABSTRACT] tags to be used on RECORD and PROCEDURE declarations.
>> > For ABSTRACT procedures the body is ignored if specified.
>> > -- OR --
>> > 2) Interpret a procedure with a single HALT(abstractMethod) statement
as an
>> > abstract method.
>>
>> Version 2 has little appeal. I would only support version 1 if any
>> system flags "[...]" are _only_ permitted if this is explicitly
>> requested in the module header. Previously oo2c disallowed system
>> flags altogether in standard modules (i.e., modules that are neiter
>> INTERFACE nor FOREIGN), currently oo2c permits them anywhere so we can
>> evaluate the necessary extensions for the Win32 API.
>
>I'd prefer version 1 too. Would a compilation error occur when a
>RECORD is declared as non-abstract, but has a type-bound procedure
>that is declared as abstract?
Yes. It should say something like "Abstract procedure X unimplemented".
>> > Comments? Language purists: please don't flame me too hard :-)
>
>In Josef Templ's dissertation "Metaprogramming in Oberon", he points
>out the need for abstract methods. He makes two suggestions for
>notations, and I liked the second one: This solution "would be to
>employ Oberon's forward-declaration mechanism and to regard
>unresolved forward methods as being abstract." In our case, a class
>that has any abstract methods would be an abstract class. I'm not
>saying this is preferable to version 1 above, but I thought I would
>share a possible alternative.
That's interesting. I haven't read Josef's work.
The advantage of the forward-declaration method that you described is that
it is an existing mechanism that allows the definition of the procedure
type without the procedure body. Ideally, abstract method declarations
should allow this.
However, I think we would want to distinguish intentional unresolved
forward-declarations from accidental ones. Admittedly, if you had
accidentally not implemented your forward-declared method, this would
probably become apparent later when you tried to use the record (as a
field, variable, or via NEW).
The reason I originally proposed option (1) is to preserve compatibility
with existing Oberon compilers. I must admit that my preference is probably
for the Component Pascal model. That is:
TYPE
a = ABSTRACT RECORD
...
END;
PROCEDURE (VAR t : a) F (x, y : INTEGER), ABSTRACT;
I assume that the equivalent with Josef's model would be:
TYPE
a = RECORD
...
END;
PROCEDURE^ (VAR t : a) F (x, y : INTEGER);
which is similar, although you can only tell that the record and procedure
are abstract from context (ie. examining the rest of the module to verify
that the procedure is unimplemented). Note that most (all?) existing
Oberon-2 compilers would not compile this, since an unresolved forward
declaration is an error.
I am suggesting that the declaration read:
TYPE
a = RECORD [ABSTRACT]
...
END;
PROCEDURE [ABSTRACT] (VAR t : a) F (x, y : INTEGER);
BEGIN
END F;
This is obviously a little more verbose. In practice, the procedure body is
irrelevant since it will never be called. This code SHOULD compile with
other Oberon-2 systems, providing they ignore the system flags (Michael
will probably tell me that I've put the flags in the wrong place :-). If it
compiles with OOC, it will run correctly on any other system too. If you
want to generate run-time exceptions, you can write:
PROCEDURE [ABSTRACT] (VAR t : a) F (x, y : INTEGER);
BEGIN
HALT(abstractMethod)
END F;
but this is probably non-portable since there is no real agreement on trap
numbers. If ABSTRACT is used consistently, your code will be correct - the
compiler won't allow abstract types to be instantiated. Since we are only
restricting allowed behaviour and not adding new functionality, correct
code should run correctly anywhere else. Of course, other Oberon systems
will allow your abstract types to be instantiated, but this can probably be
avoided by providing appropriate constructor procedures.
- Stewart