Oberon || Library || Module Index || Search Engine || Definition || Module
TYPE Object = POINTER TO ObjectRec; TYPE ObjectRec = RECORD (Disciplines.ObjectRec) END; TYPE Type = POINTER TO TypeRec; TYPE TypeRec = RECORD (Disciplines.ObjectRec) END; TYPE Service = POINTER TO ServiceRec; TYPE ServiceRec = RECORD (Disciplines.ObjectRec) END; TYPE InstallProc = PROCEDURE (object: Object; service: Service);
TYPE LoadModuleProc = PROCEDURE (module: ARRAY OF CHAR) : BOOLEAN; TYPE LoadServiceProc = PROCEDURE (service, for: ARRAY OF CHAR) : BOOLEAN; TYPE LoaderInterface = POINTER TO LoaderInterfaceRec; TYPE LoaderInterfaceRec = RECORD loadModule: LoadModuleProc; loadService: LoadServiceProc; END; PROCEDURE InitLoader(if: LoaderInterface);
PROCEDURE CreateType(VAR type: Type; name, baseName: ARRAY OF CHAR); PROCEDURE InitType(type: Type; name, baseName: ARRAY OF CHAR); PROCEDURE Init(object: Object; type: Type); PROCEDURE GetType(object: Object; VAR type: Type); PROCEDURE GetTypeName(type: Type; VAR name: ARRAY OF CHAR); PROCEDURE GetBaseType(type: Type; VAR baseType: Type); PROCEDURE IsExtensionOf(type, baseType: Type) : BOOLEAN; PROCEDURE SeekType(name: ARRAY OF CHAR; VAR type: Type);
PROCEDURE Create(VAR service: Service; name: ARRAY OF CHAR); PROCEDURE Seek(name: ARRAY OF CHAR; VAR service: Service); PROCEDURE Define(type: Type; service: Service; install: InstallProc); PROCEDURE Install(object: Object; service: Service) : BOOLEAN; PROCEDURE Supported(object: Object; service: Service) : BOOLEAN; PROCEDURE Installed(object: Object; service: Service) : BOOLEAN; PROCEDURE GetSupportedBaseType(object: Object; service: Service; VAR baseType: Type);
Based on these initializations a couple of type oriented operations are possible which extend the built-in type test and the IS operator. GetType retrieves the type of the given object. GetTypeName returns the name previously given to CreateType or InitType. GetBaseType returns the base type of a given type. NIL is returned if the type is a direct extension of Services.Object. IsExtensionOf allows to perform a type test. Giving the name of a type (e.g. "Streams.Stream"), SeekType returns the associated type. The empty string (i.e. "") and "Services.Object" must not be given because Services.Object itself is not covered by the type system.
The combination of GetType and IsExtensionOf allows to perform checks at runtime which are similar to type checks for anchored types in Eiffel:
Services.GetType(refObject, refType); Services.GetType(otherObject, otherType); IF Services.IsExtensionOf(otherType, refType) THEN (* otherObject has a type which extends that of refObject *) END;
Additionally, this module usually defines an interface and a per-object initialization procedure which has this interface as parameter. This initialization procedure is then later to be called by service providers if their install interface procedure of Service gets called. The other exported operations of this abstraction should check for a valid interface, and if not yet provided, call Install for this object, which in turn, causes the type-specific service provider to invoke the service-specific per-object initialization procedure.
There is no guarantee, however, that a service provider for a specific type exists. Consequently, each operation of a service abstraction may fail just due to the missing availability of a service provider. This possibility may be checked for by Supported which returns TRUE for the given object when the service abstraction is applicable. Installed returns TRUE if the object is already prepared for the given service.
In some cases there is no necessity for a object-specific initialization to access the service. Then the service abstraction should offer a type-specific initialization procedure which is to be called by service providers during their initialization phase. This type-specific init procedure is then free to attach a discipline to the type which references the interface of the provider. Define may then be called by the service abstraction instead of the service provider with install set to NIL. The operations of the abstraction can now check for the type of an object (by using GetSupportedBaseType) and seek for the interface at the previously attached discipline. GetSupportedBaseType must be used instead of GetType because service offers extend to all extensions of a type (if not overridden by service offers for specific derived types).
Define should be called during the initialization phase. The offered service does not only cover the given type but all its extensions, if not overridden by other providers of the same service for more specific types. The install interface procedure gets called once only for each object. Installed allows to test whether install has been called for the given object or not.
Note that naming conflicts can be easily avoided by adopting the naming conventions, i.e. by prefixing all names with the module name.
Some errors are indicated by returning a NIL-value:
Oberon || Library || Module Index || Search Engine || Definition || Module