Index: doc/example-scripts/per-object-mixins.html =================================================================== diff -u --- doc/example-scripts/per-object-mixins.html (revision 0) +++ doc/example-scripts/per-object-mixins.html (revision 23319e802e61ab370472347a8b8506bb650c8cc5) @@ -0,0 +1,966 @@ + + + + + +Listing of doc/example-scripts/per-object-mixins.tcl + + + + + +
+
+
+

NX supports "open class definitions", object specific behavior +and mixin classes (among other things) to achieve dynamic behavior +extensions. The so-called per-object mixins are actually an +implementation of the decorator pattern.

+
+
+
package req nx
+

Here is the original example: a method from a derived class +extends the behavior of the baseclass; the primitive "next" +calls other same-named methods. In the example below, the +baseclass method "speak" is called at the beginning of the +derived-class method. The primitive "next" can be placed at +arbitrary places, or it can be omitted when the baseclass method +should not be called.

+
+
+
nx::Class create BaseClass {
+  :public method speak {} {
+    puts "Hello from BC."
+  }
+}
+
+nx::Class create DerivedClass -superclass BaseClass {
+  :public method speak {} {
+    next
+    puts "Hello from DC."
+  }
+}
+
+DerivedClass create o1
+o1 speak
+

The output is:

+
+
+
   Hello from BC.
+   Hello from DC.
+
+

There are many ways to extend the behavior NX classes at +runtime. The easiest thing is to add methods dynamically to +classes. E.g. we can extend the BaseClass with the method unknown, +which is called whenever an unknown method is called.

+
+
+
BaseClass method unknown {m args} {
+  puts "What? $m? I don't understand."
+}
+o1 sing
+

The output is:

+
+
+
    What? sing? I don't understand.
+
+

Often, you do not want to extend the class, but to +modify the behavior of a single object. In NX, an object +can have individual methods:

+
+
+
o1 public method sing {} {
+  puts "Ok, here it goes: Lala Lala!"
+}
+o1 sing
+

The output is:

+
+
+
    Ok, here it goes: Lala Lala!
+
+

In many situations, it is desired to add/remove a set +of methods dynamically to objects or classes. The mechanisms +above allow this, but they are rather cumbersome and do +support a systematic behavior engineering. One can add +so-called "mixin classes" to objects and/or classes. For +example, we can define a class M for a more verbose methods:

+
+
+
nx::Class create M {
+  :public method sing {} {
+    puts -nonewline "[self] sings: "
+    next
+  }
+  :method unknown args {
+    puts -nonewline "[self] is confused: "
+    next
+  }
+}
+

The behavior of M can be mixed into the behavior of o1 through +per object mixins …

+
+
+
o1 mixin M
+
    +
  1. +

    +and we call the methods again: +

    +
  2. +
+
+
+
o1 sing
+o1 read
+

The output is:

+
+
+
   ::o1 sings: Ok, here it goes: Lala Lala!
+   ::o1 is confused: What? read? I don't understand.
+
+

We can remove the new behavior easily by unregistering the +mixin class ….

+
+
+
o1 mixin ""
+
    +
  1. +

    +and we call the methods again: +

    +
  2. +
+
+
+
o1 sing
+o1 read
+

The output is:

+
+
+
   Ok, here it goes: Lala Lala!
+   What? read? I don't understand.
+
+

Mixin classes can be used to extend the behavior of classes +as well.

+
+
+
BaseClass mixin M
+
+o1 sing
+o1 read
+
+DerivedClass create o2
+o2 read
+

The output is:

+
+
+
   ::o1 sings: Ok, here it goes: Lala Lala!
+   ::o1 is confused: What? read? I don't understand.
+   ::o2 is confused: What? read? I don't understand.
+
+
+
+
+

+ + + Index: doc/example-scripts/per-object-mixins.tcl =================================================================== diff -u --- doc/example-scripts/per-object-mixins.tcl (revision 0) +++ doc/example-scripts/per-object-mixins.tcl (revision 23319e802e61ab370472347a8b8506bb650c8cc5) @@ -0,0 +1,131 @@ +# NX supports "open class definitions", object specific behavior +# and mixin classes (among other things) to achieve dynamic behavior +# extensions. The so-called per-object mixins are actually an +# implementation of the decorator pattern. + +package req nx +package req nx::test + +# Here is the original example: a method from a derived class +# extends the behavior of the baseclass; the primitive "next" +# calls other same-named methods. In the example below, the +# baseclass method "speak" is called at the beginning of the +# derived-class method. The primitive "next" can be placed at +# arbitrary places, or it can be omitted when the baseclass method +# should not be called. + +nx::Class create BaseClass { + :public method speak {} { + puts "Hello from BC." + } +} + +nx::Class create DerivedClass -superclass BaseClass { + :public method speak {} { + next + puts "Hello from DC." + } +} + +DerivedClass create o1 +o1 speak + +# The output is: +# ---- +# Hello from BC. +# Hello from DC. +# ---- + +# There are many ways to extend the behavior NX classes at +# runtime. The easiest thing is to add methods dynamically to +# classes. E.g. we can extend the BaseClass with the method unknown, +# which is called whenever an unknown method is called. + +BaseClass method unknown {m args} { + puts "What? $m? I don't understand." +} +o1 sing + +# The output is: +# ---- +# What? sing? I don't understand. +# ---- +# +# Often, you do not want to extend the class, but to +# modify the behavior of a single object. In NX, an object +# can have individual methods: + +o1 public method sing {} { + puts "Ok, here it goes: Lala Lala!" +} +o1 sing + +# The output is: +# ---- +# Ok, here it goes: Lala Lala! +# ---- +# +# In many situations, it is desired to add/remove a set +# of methods dynamically to objects or classes. The mechanisms +# above allow this, but they are rather cumbersome and do +# support a systematic behavior engineering. One can add +# so-called "mixin classes" to objects and/or classes. For +# example, we can define a class M for a more verbose methods: + +nx::Class create M { + :public method sing {} { + puts -nonewline "[self] sings: " + next + } + :method unknown args { + puts -nonewline "[self] is confused: " + next + } +} + +# The behavior of M can be mixed into the behavior of o1 through +# per object mixins ... +o1 mixin M + +# ... and we call the methods again: +o1 sing +o1 read + +# The output is: +# ---- +# ::o1 sings: Ok, here it goes: Lala Lala! +# ::o1 is confused: What? read? I don't understand. +# ---- +# +# We can remove the new behavior easily by unregistering the +# mixin class .... + +o1 mixin "" + +# ... and we call the methods again: +o1 sing +o1 read + +# The output is: +# ---- +# Ok, here it goes: Lala Lala! +# What? read? I don't understand. +# ---- +# +# Mixin classes can be used to extend the behavior of classes +# as well. + +BaseClass mixin M + +o1 sing +o1 read + +DerivedClass create o2 +o2 read + +# The output is: +# ---- +# ::o1 sings: Ok, here it goes: Lala Lala! +# ::o1 is confused: What? read? I don't understand. +# ::o2 is confused: What? read? I don't understand. +# ----