More work in the master
branch of Vicare. Record–types now support
protection levels public
, protected
, private
for fields and
methods. I have not implemented protection levels for the parent
clause: it makes the rules for virtual methods too complex for me.
Everything I discuss here is relative to code in the head of the master
branch.
Here a copy and paste from the documentation…
When the typed language is enabled, record–type definitions support protection levels for fields and methods. Protection levels limit the way fields and methods can be used both from other types in the record–type hierarchy and from outside a record–type’s definition.
Three protection levels are supported: public
,
protected
and private
; they are loosely modeled after
the ones defined in the C++ language.
The following syntactic bindings are exported by the library
(vicare)
.
Select the public
protection level for the associated fields
and methods. When a member of record–type <T>
is given the
public
protection level: sub–types of <T>
can access it;
instances of <T>
can access it from outside methods.
When no protection level is specified for a member in a record–type
definition: the protection level defaults to public
.
Select the protected
protection level for the associated fields
and methods. When a member of record–type <T>
is given the
protected
protection level: sub–types of <T>
can access
it; instances of <T>
cannot access it from outside methods.
Select the private
protection level for the associated fields
and methods. When a member of record–type <T>
is given the
private
protection level: sub–types of <T>
cannot access
it; instances of <T>
cannot access it from outside methods.
The protection level keywords can be used both as “wrapping syntaxes” as in:
(define-record-type <duo> (public (fields one two) (method (add) (+ (.one this) (.two this)))))
or as “attribute syntaxes” as in:
(define-record-type <duo> (fields public one two) (method public (add) (+ (.one this) (.two this))))
The only clauses that can be put in a wrapping syntax and that accept an
attribute syntax are: fields
, method
,
virtual-method
, seal-method
.
The protection levels limit the access to members from outside a method’s body:
(define-record-type <blue> (method public (pub) 1) (method protected (pro) 2) (method private (pri) 3)) (define O (new <blue>)) (.pub O) ⇒ 1 (.pro O) error→ not a public method (.pri O) error→ not a public method
When super–type’s members are public
, everything works as
usual:
(define-record-type <blue> (fields public light)) (define-record-type <dark-blue> (parent <blue>) (method public (doit) (.light this))) (define O (new <dark-blue> 1)) (define {X <blue>} O) (.doit O) ⇒ 1 (.light X) ⇒ 1
When super–type’s members are protected
, we can access them
from the super–type’s methods and from the sub–type’s methods:
(define-record-type <blue> (fields protected light) (method public (doit) (.light this))) (define-record-type <dark-blue> (parent <blue>) (method public (doit) (.light this))) (define O (new <dark-blue> 1)) (.doit O) ⇒ 1 (define {X <blue>} O) (.light X) error→ not a public method (.doit X) ⇒ 1
When super–type’s members are private
, we can access them from
the super–type’s methods only:
(define-record-type <blue> (fields private light) (method public (doit) (.light this))) (define X (new <blue> 1)) (.light X) error→ not a public method (.doit X) ⇒ 1 (define-record-type <dark-blue> (parent <blue>) (method public (doit) (.light this))) error→ not a public or protected method
It is not an error to define a private virtual method, but such method cannot be overridden by the sub–types:
(define-record-type <blue> (virtual-method private (doit) 1)) (define-record-type <dark-blue> (parent <blue>) (method (doit) 2)) error→ cannot override private method
Virtual methods overriding and sealing is possible only among methods of the same protection level:
(define-record-type <blue> (protected (virtual-method (over) 'over-blue)) (method (doit) (.over this))) (define-record-type <dark-blue> (parent <blue>) (protected (method (over) 'over-dark-blue))) (define O (new <dark-blue>)) (define (fun {X <blue>}) (.doit X)) (fun O) ⇒ over-dark-blue