File: traits-composite.tcl

package info (click to toggle)
nsf 2.3.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye
  • size: 12,628 kB
  • sloc: ansic: 32,245; tcl: 10,636; sh: 664; pascal: 176; lisp: 41; makefile: 24
file content (100 lines) | stat: -rw-r--r-- 2,776 bytes parent folder | download | duplicates (4)
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