1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
|
# Implementation study based on
#
# S. Ducasse, O. Nierstrasz, N. Schärli, R. Wuyts, A. Black:
# Traits: A Mechanism for Fine-grained Reuse,
# ACM transactions on Programming Language Systems, Vol 28, No 2, March 2006
#
# Example in Fig 12: ReadStream and Trait tReadStream
#
# In this example, traits are used to extend classes and other traits.
package require nx::test
package require nx::trait
#
# Create a simple trait called +tReadStream+ which provides the
# interface to a stream. In contrary to a composite trait, a simple
# trait does not inherit from another trait.
#
nx::Trait create tReadStream {
#
# Define the methods provided by this trait:
#
:public method atStart {} {expr {[:position get] == [:minPosition]}}
:public method atEnd {} {expr {[:position get] == [:maxPosition]}}
:public method setToStart {} {set :position [:minPosition]}
:public method setToEnd {} {set :position [:maxPosition]}
:public method maxPosition {} {llength ${:collection}}
:public method on {collection} {set :collection $collection; :setToStart}
:public method next {} {
if {[:atEnd]} {return ""} else {
set r [lindex ${:collection} ${:position}]
:nextPosition
return $r
}
}
:public method minPosition {} {return 0}
:public method nextPosition {} {incr :position 1}
# This trait requires a method "position" and a variable
# "collection" from the base class. The definition is incomplete in
# these regards.
:requiredMethods position
:requiredVariables collection
}
# Define the class +ReadStream+ with properties +position+ and
# +collection+ that uses the trait. The method +require trait+ checks the
# requirements of the trait and imports the methods into +ReadStream+.
nx::Class create ReadStream {
:property {collection ""}
:property -accessor public {position 0}
:require trait tReadStream
}
# Create an instance of the class +ReadStream+:
ReadStream create r1 -collection {a b c d e}
# Test the behavior of the composed class:
? {r1 atStart} 1
? {r1 atEnd} 0
? {r1 next} a
? {r1 next} b
|