scribble trait docs

svn: r8154
This commit is contained in:
Matthew Flatt 2007-12-29 14:37:46 +00:00
parent b9cc763355
commit f80de2d73f

View File

@ -1,7 +1,8 @@
#lang scribble/doc #lang scribble/doc
@require["mz.ss"] @(require "mz.ss"
@require[scheme/class] scheme/class
@require[(for-syntax scheme/base)] (for-syntax scheme/base)
(for-label scheme/trait))
@begin[ @begin[
@ -704,7 +705,7 @@ method. The internal name is used to access the method directly within
the class expression (including within @scheme[super] or the class expression (including within @scheme[super] or
@scheme[inner] forms), while the external name is used with @scheme[inner] forms), while the external name is used with
@scheme[send] and @scheme[generic] (see @secref["ivaraccess"]). If @scheme[send] and @scheme[generic] (see @secref["ivaraccess"]). If
a single @scheme[identifier] is provided for a method declaration, the a single @scheme[id] is provided for a method declaration, the
identifier is used for both the internal and external names. identifier is used for both the internal and external names.
Method inheritance, overriding, and augmentation are based external Method inheritance, overriding, and augmentation are based external
@ -1154,6 +1155,206 @@ Evaluation of a @scheme[mixin] form checks that the
@; ------------------------------------------------------------------------ @; ------------------------------------------------------------------------
@section[#:tag "trait"]{Traits}
@note-lib-only[scheme/trait]
A @deftech{trait} is a collection of methods that can be converted to
a @tech{mixin} and then applied to a @tech{class}. Before a trait is
converted to a mixin, the methods of a trait can be individually
renamed, and multiple traits can be merged to form a new trait.
@defform/subs[#:literals (public pubment public-final override override-final overment augment augride
augment-final private inherit inherit/super inherit/inner rename-super
inherit-field)
(trait trait-clause ...)
([trait-clause (public maybe-renamed ...)
(pubment maybe-renamed ...)
(public-final maybe-renamed ...)
(override maybe-renamed ...)
(overment maybe-renamed ...)
(override-final maybe-renamed ...)
(augment maybe-renamed ...)
(augride maybe-renamed ...)
(augment-final maybe-renamed ...)
(inherit maybe-renamed ...)
(inherit/super maybe-renamed ...)
(inherit/inner maybe-renamed ...)
method-definition
(field field-declaration ...)
(inherit-field maybe-renamed ...)])]{
Creates a @tech{trait}. The body of a @scheme[trait] form is similar to the
body of a @scheme[class*] form, but restricted to non-private method
definitions. In particular, the grammar of
@scheme[maybe-renamed], @scheme[method-definition], and
@scheme[field-declaration] are the same as for @scheme[class*], and
every @scheme[method-definition] must have a corresponding declaration
(one of @scheme[public], @scheme[override], etc.). As in
@scheme[class], uses of method names in direct calls, @scheme[super]
calls, and @scheme[inner] calls depend on bringing method names into
scope via @scheme[inherit], @scheme[inherit/super],
@scheme[inherit/inner], and other method declarations in the same
trait; an exception, compared to @scheme[class] is that
@scheme[overment] binds a method name only in the corresponding
method, and not in other methods of the same trait. Finally, macros
such as @scheme[public*] and @scheme[define/public] work in
@scheme[trait] as in @scheme[class].
External identifiers in @scheme[trait], @scheme[trait-exclude],
@scheme[trait-exclude-field], @scheme[trait-alias],
@scheme[trait-rename], and @scheme[trait-rename-field] forms are
subject to binding via @scheme[define-member-name] and
@scheme[define-local-member-name]. Although @scheme[private] methods
or fields are not allowed in a @scheme[trait] form, they can be
simulated by using a @scheme[public] or @scheme[field] declaration and
a name whose scope is limited to the @scheme[trait] form.}
@defproc[(trait? [v any/c]) boolean?]{
Returns @scheme[#t] if @scheme[v] is a trait, @scheme[#f] otherwise.}
@defproc[(trait->mixin [tr trait?]) (class? . -> . class?)]{
Converts a @tech{trait} to a @tech{mixin}, which can be applied to a
@tech{class} to produce a new @tech{class}. An expression of the form
@schemeblock[
(trait->mixin
(trait
trait-clause ...))
]
is equivalent to
@schemeblock[
(lambda (%)
(class %
trait-clause ...
(super-new)))
]
Normally, however, a trait's methods are changed and combined with
other traits before converting to a mixin.}
@defproc[(trait-sum [tr trait?] ...+) trait?]{
Produces a @tech{trait} that combines all of the methods of the given
@scheme[tr]s. For example,
@schemeblock[
(define t1
(trait
(define/public (m1) 1)))
(define t2
(trait
(define/public (m2) 2)))
(define t3 (trait-sum t1 t2))
]
creates a trait @scheme[t3] that is equivalent to
@schemeblock[
(trait
(define/public (m1) 1)
(define/public (m2) 2))
]
but @scheme[t1] and @scheme[t2] can still be used individually or
combined with other traits.
When traits are combined with @scheme[trait-sum], the combination
drops @scheme[inherit], @scheme[inherit/super],
@scheme[inherit/inner], and @scheme[inherit-field] declarations when a
definition is supplied for the same method or field name by another
trait. The @scheme[trait-sum] operation fails (the
@exnraise[exn:fail:contract]) if any of the traits to combine define a
method or field with the same name, or if an @scheme[inherit/super] or
@scheme[inherit/inner] declaration to be dropped is inconsistent with
the supplied definition. In other words, declaring a method with
@scheme[inherit], @scheme[inherit/super], or @scheme[inherit/inner],
does not count as defining the method; at the same time, for example,
a trait that contains an @scheme[inherit/super] declaration for a
method @scheme[m] cannot be combinaed with a trait that defines
@scheme[m] as @scheme[augment], since no class could satisfy the
requirements of both @scheme[augment] and @scheme[inherit/super] when
the trait is later converted to a mixin and applied to a class.}
@defform[(trait-exclude trait-expr id)]{
Produces a new @tech{trait} that is like the @tech{trait} result of
@scheme[trait-expr], but with the definition of a method named by
@scheme[id] removed; as the method definition is removed, either a
@scheme[inherit], @scheme[inherit/super], or @scheme[inherit/inner]
declaration is added:
@itemize{
@item{A method declared with @scheme[public], @scheme[pubment], or
@scheme[public-final] is replaced with a @scheme[inherit]
declaration.}
@item{A method declared with @scheme[override] or @scheme[override-final]
is replaced with a @scheme[inherit/super] declaration.}
@item{A method declared with @scheme[augment], @scheme[augride], or
@scheme[augment-final] is replaced with a @scheme[inherit/inner] declaration.}
@item{A method declared with @scheme[overment] is not replaced
with any @scheme[inherit] declaration.}
}
If the trait produced by @scheme[trait-expr] has no method definition for
@scheme[id], the @exnraise[exn:fail:contract].}
@defform[(trait-exclude-field trait-expr id)]{
Produces a new @tech{trait} that is like the @tech{trait} result of
@scheme[trait-expr], but with the definition of a field named by
@scheme[id] removed; as the field definition is removed, an
@scheme[inherit-field] declaration is added.}
@defform[(trait-alias trait-expr id new-id)]{
Produces a new @tech{trait} that is like the @tech{trait} result of
@scheme[trait-expr], but the definition and declaration of the method
named by @scheme[id] is duplicated with the name @scheme[new-id]. The
consistency requirements for the resulting trait are the same as for
@scheme[trait-sum], otherwise the @exnraise[exn:fail:contract]. This
operation does not rename any other use of @scheme[id], such as in
method calls (even method calls to @scheme[identifer] in the cloned
definition for @scheme[new-id]).}
@defform[(trait-rename trait-expr id new-id)]{
Produces a new @tech{trait} that is like the @tech{trait} result of
@scheme[trait-expr], but all definitions and references to methods
named @scheme[id] are replaced by definitions and references to
methods named by @scheme[new-id]. The consistency requirements for the
resulting trait is the same as for @scheme[trait-sum], otherwise the
@exnraise[exn:fail:contract].}
@defform[(trait-rename-field trait-expr id new-id)]{
Produces a new @tech{trait} that is like the @tech{trait} result of
@scheme[trait-expr], but all definitions and references to fields
named @scheme[id] are replaced by definitions and references to fields
named by @scheme[new-id]. The consistency requirements for the
resulting trait is the same as for @scheme[trait-sum], otherwise the
@exnraise[exn:fail:contract].}
@; ------------------------------------------------------------------------
@section{Object and Class Contracts} @section{Object and Class Contracts}
@defform/subs[ @defform/subs[