In SICStus Objects, each method is executed in the context of an object.
This object may not be the static object where the method is
declared. The current contextual object is used to determine
dynamically which attributes are accessed, and which methods are
called. This leads to a mechanism known as dynamic binding. This object
can be retrieved using the universal method self(
S)
, where
S will be bound to the current contextual object.
When a message is sent to an object, the corresponding method will be executed in the context of the target object. A message delegated to an object will invoke a method that is executed in the context of the message-delegation operation.
Message sending. Sends message to object, setting
Self of the recipient to the recipient, i.e. object. If
object is omitted, the recipient is the object in which the
goal textually appears.
Message delegation. Sends message to object, setting Self of the recipient to Self of the sender. If object is omitted, the recipient is the object in which the goal textually appears. Delegation preserves Self.
The following objects physical_object
, a
, and b
are
written using the default notations for sending and delegation, hiding the
contextual variable Self:
physical_object :: { volume(50) & density(100) & weight(X) :- volume(V), density(D), :(X is V*D) }. a :: { volume(5) & density(10) & Method :- physical_object <: Method }. b :: { volume(5) & density(10) & Method :- physical_object :: Method }.
Notice that the difference between the objects a
and b
is
that a
delegates any message except volume(_)
and
density(_)
to physical_object
while b
sends
the message to physical_object
. We may now ask
| ?- a :: weight(X), b :: weight(Y). X = 50 Y = 5000
To get hold of the current contextual object, the universal method
self(
S)
is provided. Another way to send a message to
Self is to use the constant self
. So the following
two alternative definition of physical_object
are equivalent to
the previous one:
physical_object :: { volume(50) & density(100) & weight(X) :- self(S), S::volume(V), S::density(D), :(X is V*D) }. physical_object :: { volume(50) & density(100) & weight(X) :- self::volume(V), self::density(D), :(X is V*D) }.