[ << ] | [ < ] | [ Up ] | [ > ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
10.4 Widening and shrinking
Bigloo introduces a new kind of inheritance: widening. This allows an object to be temporarily widened (that is transformed into an object of another class, a wide-class) and then shrink-ed (that is reshaped to its original class). This mechanism is very useful for implementing short-term data storage. For instance, Bigloo compilation passes are implemented using the widening/shrinking mechanism. On entry to a pass, objects are widened with the specific pass fields and, on exit from a pass, objects are shrunk in order to forget the information related to this pass.
Only instances of final classes can be widened and objects can
only be widened in order to become instances of wide classes.
Widening is performed by the widen!
syntax:
- bigloo syntax: widen!::wide-class obj (id value) …
-
The object obj is widened to be instance of the wide class wide-class. Fields values are either picked up from the parameter list of the
widen!
form or from the default values in the declaration of the wide class.
Objects are shrunk using the shrink!
syntax:
Here is a first example:
(module example (static (final-class point (x (default 0)) (y (default 0))) (wide-class named-point::point name))) (define *point* (instantiate::point))
Two classes have been declared and an instance *point*
of
point
has been allocated. For now, *point*
is an instance
of point
but not an instance of named-point
and this can
be checked by:
(print (isa? *point* named)) → #t (print (isa? *point* named-point)) → #f
Now, we widen *point*
...
(let ((n-point (widen!::named-point *point* (name "orig"))))
And we check that now, n-point
is an instance of
named-point
. Since named-point
is a subclass of
point
, n-point
still is an instance of point
.
(print (isa? n-point named-point)) → #t (print (isa? n-point named)) → #t
Widening affects the objects themselves. It does not operate any
copy operation. Hence, *point*
and n-point
are eq?
.
(print (eq? n-point *point*)) → #t
To end this example, we shrink n-point
and check
its class.
(shrink! n-point) (print (isa? *point* named-point))) → #f
Here is a more complex example:
We illustrate widening and shrinking using our “wedding simulator”.
First let us define three classes, person
(for man and woman),
married-woman
and married-man
:
(module wedding (static (final-class person name::string fname::string (sex::symbol read-only)) (wide-class married-man::person mate::person) (wide-class married-woman::person maiden-name::string mate::person)))
As we can see people are allowed to change their name but not their sex.
The identity of a person can be printed as
(define-method (object-display p::person . op) (with-access::person p (name fname sex) (print "firstname : " fname) (print "name : " name) (print "sex : " sex) p))
A married woman’s identity is printed by (we suppose an equivalent method definition for married-man)
(define-method (object-display p::married-woman . op) (with-access::married-woman p (name fname sex mate) (call-next-method) (print "married to: " mate) p))
We create a person with the birth
function:
(define (birth name::string fname::string sex) [assert (sex) (memq sex '(male female))] (instantiate::person (name name) (fname fname) (sex sex)))
We celebrate a wedding using the get-married!
function:
(define (get-married! woman::person man::person) (if (not (and (eq? (-> woman sex) 'female) (eq? (-> man sex) 'male))) (error "get-married" "Illegal wedding" (cons woman man)) (let* ((mname (-> woman name)) (wife (widen!::married-woman woman (maiden-name mname) (mate man)))) (person-name-set! wife (-> man name)) (widen!::married-man man (mate woman)))))
We can check if two people are married by
(define (couple? woman::person man::person) (and (isa? woman married-woman) (isa? man married-man) (eq? (with-access::married-woman woman (mate) mate) man) (eq? (with-access::married-man man (mate) mate) woman)))
Now let us study the life a Junior
Jones
and
Pamela
Smith
. Once upon a time...
(define *junior* (birth "Jones" "Junior" 'male)) (define *pamela* (birth "Smith" "Pamela" 'female))
Later on, they met each other and ... they got married:
(define *old-boy-junior* *junior*) (define *old-girl-pamela* *pamela*) (get-married! *pamela* *junior*)
This union can be checked:
(couple? *pamela* *junior*) ⇒ #t
We can look at the new identity of *pamela*
(print *pamela*) -| name : Jones firstname : Pamela sex : FEMALE married to: Junior Jones
But *pamela*
and *junior*
still are the same persons:
(print (eq? *old-boy-junior* *junior*)) ⇒ #t (print (eq? *old-girl-pamela* *pamela*)) ⇒ #t
Unfortunately all days are not happy days. After having been married
*pamela*
and *junior*
have divorced:
(define (divorce! woman::person man::person) (if (not (couple? woman man)) (error "divorce!" "Illegal divorce" (cons woman man)) (with-access::married-woman woman (maiden-name) (begin (shrink! woman) (set! (-> woman name) maiden-name)) (shrink! man)))) (divorce! *pamela* *junior*)
We can look at the new identity of *pamela*
(print *pamela*) -| name : Smith firstname : Pamela sex : FEMALE
And *pamela*
and *junior*
still are the same persons:
(print (eq? *old-boy-junior* *junior*)) ⇒ #t (print (eq? *old-girl-pamela* *pamela*)) ⇒ #t
[ << ] | [ < ] | [ Up ] | [ > ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This document was generated on March 31, 2014 using texi2html 5.0.