Run time usage of objects

Author(s): Angel Fernandez Pineda, Angel Fernandez Pineda.

This library provides run-time support for object creation and manipulation. Objects are also called class instances, or simply instances.

Objects in Ciao are treated as normal modules. This is, an object is a run-time generated Prolog module, which may be identified by an unique term across the whole application.

This is a very simple example of how to create an instance, and how to make calls to it:

            AnObj new myclass,
            AnObj:mymethod.
         

In order to make any object accessible from code, an usage relationship must be established between the class (from which instances are derived) and the code itself. Refer to use_class/1 predicate or use_class/1 declaration in order to do so.

Usage and interface

Documentation on exports

PREDICATE
Dynamic instance creation takes place by the ways of this predicate.

It takes a free variable as first argument which will be instantiated to an internal object identifier.

Second argument must be instantiated to a class constructor. Class constructors are designed to perform an initialization on the new created instance. Notice that instance initialization may involve some kind of computation, not only state initialization.

A class constructor is made by a functor, which must match the intended class name, and any number of parameters. For example:

            Obj new myclass(1500,'hello, world!!!')
         

Those parameters depends (obviously) on the constructors defined at the class source. If no constructors where defined, no parameters are needed. This is called the default constructor. An example:

            Obj new myclass
         

The default constructor can not be called if there is any constructor available at the class source.

Instantiation will raise an exception and fail whenever any of this conditions occur:

  • First argument is not a free variable.
  • Second argument functor is a class, but there is no usage relationship with it.
  • Second argument functor is not a class.
  • The given constructor is unknown.
  • The given constructor fails (notice that default constructor never fails).

Objects may also be statically declared, refer to instance_of/2 declaration.

Usage: new(InstanceVar,Constructor)

  • Description: Creates a new instance of the class specified by Constructor returning its identifier in InstanceVar
  • The following properties should hold at call time:
    (term_typing:var/1)InstanceVar is a free variable.
    (objects_rt:constructor/1)Constructor is a term whose functor matches a class name.
  • The following properties should hold upon exit:
    (objects_rt:instance_id/1)InstanceVar is an unique term which identifies an object.

PREDICATE
This predicate is used to perform dynamic type checking. You may check whether a particular instance belongs to a particular class or related descendants.

instance_of/2 is used to perform static semantic analisys over object oriented code constructions.

By the use of instance_of/2 you may help to perform such analisys.

Usage 1: instance_of(Instance,Class)

  • Description: Test whether Instance was derived from any descendant of Class, or that class itself
  • The following properties should hold at call time:
    (objects_rt:instance_id/1)Instance is an unique term which identifies an object.
    (objects_rt:class_name/1)Class is an atom denoting a class.

Usage 2: instance_of(Instance,Class)

  • Description: Retrieves, on backtracking, the inheritance line of Instance commencing on the creation class (that specified on call to new/2) and continuing on the rest of ascendant classes, if any.
  • The following properties should hold at call time:
    (objects_rt:instance_id/1)Instance is an unique term which identifies an object.
    (term_typing:var/1)Class is a free variable.
  • The following properties should hold upon exit:
    (objects_rt:class_name/1)Class is an atom denoting a class.

PREDICATE
Test whether an object identifier was derived directly from a class, by the usage of new/2 or a static instance declaration (instance_of/2).

Usage 1: derived_from(Instance,Class)

  • Description: Test derivation of Instance from Class
  • The following properties should hold at call time:
    (objects_rt:instance_id/1)Instance is an unique term which identifies an object.
    (objects_rt:class_name/1)Class is an atom denoting a class.

Usage 2: derived_from(Instance,Class)

  • Description: Retrieves the Class responsable of the derivation of Instance.
  • The following properties should hold at call time:
    (objects_rt:instance_id/1)Instance is an unique term which identifies an object.
    (term_typing:var/1)Class is a free variable.
  • The following properties should hold upon exit:
    (objects_rt:class_name/1)Class is an atom denoting a class.

PREDICATE
This predicate is used to ensure a given interface to be implemented by a given instance.

Usage 1: interface(Instance,Interface)

  • Description: Check whether Instance implements the given Interface.
  • The following properties should hold at call time:
    (objects_rt:instance_id/1)Instance is an unique term which identifies an object.
    (objects_rt:interface_name/1)Interface is an unique atom which identifies a public interface.

Usage 2: interface(Instance,Interfaces)

  • Description: Retrieves on backtracking all the implemented Interfaces of Instance.
  • The following properties should hold at call time:
    (objects_rt:instance_id/1)Instance is an unique term which identifies an object.
    (term_typing:var/1)Interfaces is a free variable.
  • The following properties should hold upon exit:
    (objects_rt:interface_name/1)Interfaces is an unique atom which identifies a public interface.

PREDICATE
Retrieves a character string representation from an object identifier and vice-versa.

Usage 1: instance_codes(Instance,String)

  • Description: Retrieves a String representation of given Instance.
  • The following properties should hold at call time:
    (objects_rt:instance_id/1)Instance is an unique term which identifies an object.
    (term_typing:var/1)String is a free variable.
  • The following properties should hold upon exit:
    (basic_props:string/1)String is a string (a list of character codes).

Usage 2: instance_codes(Instance,String)

  • Description: Reproduces an Instance from its String representation. Such an instance must be alive across the application: this predicate will fail whether the involved instance has been destroyed.
  • The following properties should hold at call time:
    (term_typing:var/1)Instance is a free variable.
    (basic_props:string/1)String is a string (a list of character codes).
  • The following properties should hold upon exit:
    (objects_rt:instance_id/1)Instance is an unique term which identifies an object.

PREDICATE
As well as instances are created, they must be destroyed when no longer needed in order to release system resources.

Unfortunately, current O'Ciao implementation does not support automatic instance destruction, so user must manually call destroy/1 in order to do so.

The programmer must ensure that no other references to the involved object are left in memory when destroy/1 is called. If not, unexpected results may be obtained.

Usage: destroy(Instance)

  • Description: Destroys the object identified by Instance.
  • The following properties should hold at call time:
    (objects_rt:instance_id/1)Instance is an unique term which identifies an object.

PREDICATE
The behaviour of this predicate is identical to that provided by the declaration of the same name use_class/1. It allows user programs to dynamically load classes. Whether the given source is not a class it will perform a use_module/1 predicate call.

Usage: use_class(ClassSource)

  • Description: Dynamically loads the given ClassSource
  • The following properties should hold at call time:
    (objects_rt:class_source/1)ClassSource is a valid path to a prolog file containing a class declaration (without .pl extension).

PROPERTY

Usage: constructor(Cons)

  • Description: Cons is a term whose functor matches a class name.

PROPERTY

Usage: class_name(ClassName)

  • Description: ClassName is an atom denoting a class.

PROPERTY

Usage: interface_name(Interface)

  • Description: Interface is an unique atom which identifies a public interface.

PROPERTY

Usage: instance_id(ID)

  • Description: ID is an unique term which identifies an object.

PROPERTY

Usage: class_source(Source)

  • Description: Source is a valid path to a prolog file containing a class declaration (without .pl extension).

PROPERTY

Usage: interface_source(Source)

  • Description: Source is a valid path to a prolog file containing a class declaration or an interface declaration (without .pl extension).

PROPERTY
There is no difference between method or attribute specifications, and habitual predicate specifications. It is just a Functor/Arity term.

Usage: method_spec(Spec)

  • Description: Spec is a method or attribute specification.

PROPERTY

Usage: virtual_method_spec(Spec)

  • Description: Spec is a method specification.

Known bugs and planned improvements

  • Usage of objects from the user module does not work properly. It is better to use the objects package in a (proper) module.
  • Not really a bug: when loading code which declares static instances from the toplevel shell, predicate use_module/1) will not work properly: those instances may be not correctly created, and predicates will fail whenever they are not supposed to do. This may be avoided by reloading again the involved module, but make sure it is modified and saved to disk before doing so.