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 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
|
# 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
#
# Fig 13: tReadStream and tWriteStream as composite traits
#
# In this example, traits are used to extend classes and other traits
# (called then _composite traits_).
#
package req nx::test
package req nx::trait
#
# Create a Trait called +tPositionableStream+
#
nx::Trait create tPositionableStream {
#
# 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 minPosition {} {return 0}
:public method nextPosition {} {incr :position 1}
# The trait requires a method "position" and a variable "collection"
# from the base class or other traits. The definition is incomplete
# in these regards
:requiredMethods position
:requiredVariables collection
}
#
# Create a composite trait called +tReadStream+ based on the trait
# +tPositionableStream+:
#
nx::Trait create tReadStream {
#
# Methods provided by this trait:
#
:public method on {collection} {set :collection $collection; :setToStart}
:public method next {} {
if {[:atEnd]} {return ""} else {
set r [lindex ${:collection} ${:position}]
:nextPosition
return $r
}
}
# This trait requires these methods:
:requiredMethods {setToStart atEnd nextPosition}
# Require the trait "tPositionableStream"
:require trait tPositionableStream
}
#
# Create a composite trait called +tWriteStream+ based on the trait
# +tPositionableStream+:
#
nx::Trait create tWriteStream {
#
# Methods provided by this trait:
#
:public method on {collection} {set :collection $collection; :setToEnd}
:public method nextPut {element} {
lappend :collection $element
:nextPosition
return ""
}
# This trait requires these methods:
:requiredMethods {setToEnd nextPosition}
# Require the trait "tPositionableStream"
:require trait tPositionableStream
}
# Define a class +ReadStream+ with properties +position+ and
# +collection+ that uses the composite trait +tReadStream+:
nx::Class create ReadStream {
:property {collection ""}
:property -accessor public {position 0}
:require trait tReadStream
}
# Create an instance of +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
|