File: rosetta-singleton.tcl

package info (click to toggle)
nsf 2.4.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 13,208 kB
  • sloc: ansic: 32,687; tcl: 10,723; sh: 660; pascal: 176; javascript: 135; lisp: 41; makefile: 24
file content (55 lines) | stat: -rw-r--r-- 1,671 bytes parent folder | download | duplicates (2)
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
#
# == Rosetta Example: Singleton 
# For details see https://rosettacode.org/wiki/Singleton
#
# === A Singleton Class
package req nx
package req nx::test

nx::Class create Singleton {
  #
  # We overload the system method "create". In the modified method we
  # save the created instance in the instance variable named
  # "instance"
  #
  :variable instance:object

  :public object method create {args} {
    return [expr {[info exists :instance] ? ${:instance} : [set :instance [next]]}]
  }
}

# === Demonstrating the behavior in a shell: 
#
# Calling  +Singleton new+ multiple times returns always the same object:
? {expr {[Singleton new] eq [Singleton new]}} 1

#
# === A Singleton Meta-class
#
# Alternatively, we can follow a more generic approach and define a
# metaclass which allows one to define several application classes as
# singletons. The metaclass has the most general metaclass +nx::Class+
# as superclass. In contrary to the example obove, the +create+ method
# is not defined as a class method, but it will be inherited to its
# instances (to the application classes).
# 
nx::Class create Singleton -superclass nx::Class {
  #
  # We overload the system method "create". In the modified method we
  # save the created instance in the instance variable named
  # "instance"
  #
  :variable instance:object

  :public method create {args} {
    return [expr {[info exists :instance] ? ${:instance} : [set :instance [next]]}]
  }
}

# Create an application class named +Counter+ as a singleton:

? {Singleton create Counter} ::Counter

# Calling  +Counter new+ multiple times returns always the same object:
? {expr {[Counter new] eq [Counter new]}} 1