Objects are created with the
create/2 predicate. When you define a
class, you must specify all the ways that instances of the class can
be created. The simplest creation method is defined as
Self <- create.
If this method were defined for Class, then the command
| ?- create(Class,
would create an instance of Class and bind the variable
Object to that
instance. All slots would receive their (possibly default) initial
More generally, if the definition for Class contains a create method
Self <- create(Arguments) :- Body.
then the command
| ?- create(Class(Arguments), Object).
will create an instance of Class and execute the Body of the create method, using the specified Arguments. The variable Object is bound to the new instance.
If a simple class definition has no create methods, then it is impossible create instances of the class. While the absence of create methods may be a programmer error, that is not always the case. Abstract classes, which are classes that cannot have instances, are often quite useful in defining a class hierarchy.
Create methods can be used to initialize slots in situations when specifying initial slot values will not suffice. (Remember that initial values must be specified as constants at compile time). The simplest case uses the arguments of the create message as initial slot values. For example, the definition of the point class might contain the following create method.
Self <- create(X,Y) :- Self << x(X), Self << y(Y).
If used as follows
| ?- create(point(3.14159, 2.71828), PointObj), PointObj >> x(X), PointObj >> y(Y).
it would give
Y the values of 3.14159 and 2.71828, respectively.
In some cases, the create method might compute the initial values. The
following (partial) class definition uses the
date/1 predicate from
library(date) to initialize its year, month and day slots.
:- class date_stamp = [year:integer, month:integer, day:integer]. Self <- create :- date(date(Year, Month, Day)), store_slot(year, Year), store_slot(month, Month), store_slot(day, Day).
All three slots are private, so it will be necessary to define get
methods in order to retrieve the time information. If no put methods
are defined, however, the date cannot be modified after
date_stamp object is created (unless some other method for
this class invokes
Create methods can do more than initialize slot values. Consider the
named_point class, whose definition begins as follows:
:- class named_point = [public name:atom, public x:float=1, public y:float=0]. Self <- create(Name, X, Y) :- Self << name(Name), Self << x(X), Self << y(Y), assert(name_point(Name, Self)).
Not only does the
create/3 message initialize the slots of a new
named_point object, but it also adds a
name_point/2 fact to
the Prolog database, allowing each new object to be found by its
name. (This create method does not require the
to have a unique name. Defining a
uniq_named_point class is left
as an exercise.)
An object is destroyed with the
destroy/1 command. Unlike
destroy/1 does not require that you define a
method for a class. However,
destroy/1 will send a destroy message
(with no arguments) to an object before it is destroyed, if a
destroy method is
defined for the object's class.
named_point object is ever destroyed, the address of the
object stored in this name
point/2 fact is no longer valid. Hence,
there should be a corresponding destroy method that retracts it.
Self <- destroy :- Self >> name(Name), retract(name_point(Name, Self)).
Similar create and destroy methods can be defined for objects that allocate their own separate memory or that announce their existence to foreign code.