As can be seen in the expanded methods above, the second additional argument is simply ignored if the object has no parameter. In contrast regard the following objects:
ellipse(RX,RY,Color) :: { color(Color) & area(A) :- :(A is RX*RY*3.14159265) }. circle(R,Color) :: { super(ellipse(R,R,Color)) }. red_circle(R) :: { super(circle(R,red)) }.
... and their expansions:
ellipse(_, _, _):'$so_type'(ellipse(_,_,_), static). ellipse(_, _, _):area(A, _, B) :- B:'$fix_param'(ellipse(C,D,_), B), user:(A is C*D*3.14159265). ellipse(_, _, _):color(A, _, B) :- B:'$fix_param'(ellipse(_,_,A), B). ellipse(_, _, _):'$fix_param'(ellipse(B,C,D), A) :- objects:object_class(ellipse(B,C,D), A). circle(_, _):'$so_type'(circle(_,_), static). circle(_, _):super(ellipse(A,A,B), [], _, circle(A,B)). circle(_, _):'$fix_param'(circle(B,C), A) :- objects:object_class(circle(B,C), A). circle(_, _):'$fix_param'(ellipse(B,B,C), A) :- objects:object_class(circle(B,C), A). red_circle(_):'$so_type'(red_circle(_), static). red_circle(_):super(circle(A,red), [], _, red_circle(A)). red_circle(_):'$fix_param'(red_circle(B), A) :- objects:object_class(red_circle(B), A). red_circle(_):'$fix_param'(circle(B,red), A) :- objects:object_class(red_circle(B), A). red_circle(_):'$fix_param'(ellipse(B,B,red), A) :- objects:object_class(red_circle(B), A).
The second additional argument contains the receiver of a method
call. If the method makes use of any parameter of the object where it is
defined, it places a call to the reserved predicate
$fix_param/2
in the module of the receiver. The purpose of
this call is to bind the parameters used in the method to
appropriate values given by the receiver. The receiver may be the object
where the method is defined or any of its subs. In order to service
these calls, a clause of $fix_param/2
is generated for each
ancestor having parameters. Such a clause may be regarded as
the collapsed chain of super/[1,2]
definitions leading up to the
ancestor.
The call objects:object_class(
Class,
Object)
serves to
pick up the '$class'/1
attribute if Object is an instance;
otherwise, Class is unified with Object.
The following trace illustrates how parameters are transfered:
| ?- red_circle(2.5)::area(A). 1 1 Call: red_circle(2.5)::area(_A) ? <RET> 2 2 Call: ellipse(_,_,_):area(_A,red_circle(2.5),red_circle(2.5)) ? <RET> 3 3 Call: red_circle(_):$fix_param(ellipse(_B,_,_),red_circle(2.5)) ? <RET> 4 4 Call: objects:object_class(red_circle(_B),red_circle(2.5)) ? <RET> 4 4 Exit: objects:object_class(red_circle(2.5),red_circle(2.5)) ? <RET> 3 3 Exit: red_circle(_):$fix_param(ellipse(2.5,2.5,red),red_circle(2.5)) ? <RET> 5 3 Call: _A is 2.5*2.5*3.14159265 ? <RET> 5 3 Exit: 19.6349540625 is 2.5*2.5*3.14159265 ? <RET> 2 2 Exit: ellipse(_,_,_):area(19.6349540625,red_circle(2.5),red_circle(2.5)) ? <RET> 1 1 Exit: red_circle(2.5)::area(19.6349540625) ? <RET> A = 19.6349540625