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) }.