<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
<meta name="generator" content="AsciiDoc 8.6.5" />
<title>Listing of doc/example-scripts/per-object-mixins.tcl</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */

/* Default font. */
body {
  font-family: Georgia,serif;
}

/* Title font. */
h1, h2, h3, h4, h5, h6,
div.title, caption.title,
thead, p.table.header,
#toctitle,
#author, #revnumber, #revdate, #revremark,
#footer {
  font-family: Arial,Helvetica,sans-serif;
}

body {
  margin: 1em 5% 1em 5%;
}

a {
  color: blue;
  text-decoration: underline;
}
a:visited {
  color: fuchsia;
}

em {
  font-style: italic;
  color: navy;
}

strong {
  font-weight: bold;
  color: #083194;
}

h1, h2, h3, h4, h5, h6 {
  color: #527bbd;
  margin-top: 1.2em;
  margin-bottom: 0.5em;
  line-height: 1.3;
}

h1, h2, h3 {
  border-bottom: 2px solid silver;
}
h2 {
  padding-top: 0.5em;
}
h3 {
  float: left;
}
h3 + * {
  clear: left;
}
h5 {
  font-size: 1.0em;
}

div.sectionbody {
  margin-left: 0;
}

hr {
  border: 1px solid silver;
}

p {
  margin-top: 0.5em;
  margin-bottom: 0.5em;
}

ul, ol, li > p {
  margin-top: 0;
}
ul > li     { color: #aaa; }
ul > li > * { color: black; }

pre {
  padding: 0;
  margin: 0;
}

#author {
  color: #527bbd;
  font-weight: bold;
  font-size: 1.1em;
}
#email {
}
#revnumber, #revdate, #revremark {
}

#footer {
  font-size: small;
  border-top: 2px solid silver;
  padding-top: 0.5em;
  margin-top: 4.0em;
}
#footer-text {
  float: left;
  padding-bottom: 0.5em;
}
#footer-badges {
  float: right;
  padding-bottom: 0.5em;
}

#preamble {
  margin-top: 1.5em;
  margin-bottom: 1.5em;
}
div.imageblock, div.exampleblock, div.verseblock,
div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
div.admonitionblock {
  margin-top: 1.0em;
  margin-bottom: 1.5em;
}
div.admonitionblock {
  margin-top: 2.0em;
  margin-bottom: 2.0em;
  margin-right: 10%;
  color: #606060;
}

div.content { /* Block element content. */
  padding: 0;
}

/* Block element titles. */
div.title, caption.title {
  color: #527bbd;
  font-weight: bold;
  text-align: left;
  margin-top: 1.0em;
  margin-bottom: 0.5em;
}
div.title + * {
  margin-top: 0;
}

td div.title:first-child {
  margin-top: 0.0em;
}
div.content div.title:first-child {
  margin-top: 0.0em;
}
div.content + div.title {
  margin-top: 0.0em;
}

div.sidebarblock > div.content {
  background: #ffffee;
  border: 1px solid #dddddd;
  border-left: 4px solid #f0f0f0;
  padding: 0.5em;
}

div.listingblock > div.content {
  border: 1px solid #dddddd;
  border-left: 5px solid #f0f0f0;
  background: #f8f8f8;
  padding: 0.5em;
}

div.quoteblock, div.verseblock {
  padding-left: 1.0em;
  margin-left: 1.0em;
  margin-right: 10%;
  border-left: 5px solid #f0f0f0;
  color: #777777;
}

div.quoteblock > div.attribution {
  padding-top: 0.5em;
  text-align: right;
}

div.verseblock > pre.content {
  font-family: inherit;
  font-size: inherit;
}
div.verseblock > div.attribution {
  padding-top: 0.75em;
  text-align: left;
}
/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
div.verseblock + div.attribution {
  text-align: left;
}

div.admonitionblock .icon {
  vertical-align: top;
  font-size: 1.1em;
  font-weight: bold;
  text-decoration: underline;
  color: #527bbd;
  padding-right: 0.5em;
}
div.admonitionblock td.content {
  padding-left: 0.5em;
  border-left: 3px solid #dddddd;
}

div.exampleblock > div.content {
  border-left: 3px solid #dddddd;
  padding-left: 0.5em;
}

div.imageblock div.content { padding-left: 0; }
span.image img { border-style: none; }
a.image:visited { color: white; }

dl {
  margin-top: 0.8em;
  margin-bottom: 0.8em;
}
dt {
  margin-top: 0.5em;
  margin-bottom: 0;
  font-style: normal;
  color: navy;
}
dd > *:first-child {
  margin-top: 0.1em;
}

ul, ol {
    list-style-position: outside;
}
ol.arabic {
  list-style-type: decimal;
}
ol.loweralpha {
  list-style-type: lower-alpha;
}
ol.upperalpha {
  list-style-type: upper-alpha;
}
ol.lowerroman {
  list-style-type: lower-roman;
}
ol.upperroman {
  list-style-type: upper-roman;
}

div.compact ul, div.compact ol,
div.compact p, div.compact p,
div.compact div, div.compact div {
  margin-top: 0.1em;
  margin-bottom: 0.1em;
}

tfoot {
  font-weight: bold;
}
td > div.verse {
  white-space: pre;
}

div.hdlist {
  margin-top: 0.8em;
  margin-bottom: 0.8em;
}
div.hdlist tr {
  padding-bottom: 15px;
}
dt.hdlist1.strong, td.hdlist1.strong {
  font-weight: bold;
}
td.hdlist1 {
  vertical-align: top;
  font-style: normal;
  padding-right: 0.8em;
  color: navy;
}
td.hdlist2 {
  vertical-align: top;
}
div.hdlist.compact tr {
  margin: 0;
  padding-bottom: 0;
}

.comment {
  background: yellow;
}

.footnote, .footnoteref {
  font-size: 0.8em;
}

span.footnote, span.footnoteref {
  vertical-align: super;
}

#footnotes {
  margin: 20px 0 20px 0;
  padding: 7px 0 0 0;
}

#footnotes div.footnote {
  margin: 0 0 5px 0;
}

#footnotes hr {
  border: none;
  border-top: 1px solid silver;
  height: 1px;
  text-align: left;
  margin-left: 0;
  width: 20%;
  min-width: 100px;
}

div.colist td {
  padding-right: 0.5em;
  padding-bottom: 0.3em;
  vertical-align: top;
}
div.colist td img {
  margin-top: 0.3em;
}

@media print {
  #footer-badges { display: none; }
}

#toc {
  margin-bottom: 2.5em;
}

#toctitle {
  color: #527bbd;
  font-size: 1.1em;
  font-weight: bold;
  margin-top: 1.0em;
  margin-bottom: 0.1em;
}

div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
  margin-top: 0;
  margin-bottom: 0;
}
div.toclevel2 {
  margin-left: 2em;
  font-size: 0.9em;
}
div.toclevel3 {
  margin-left: 4em;
  font-size: 0.9em;
}
div.toclevel4 {
  margin-left: 6em;
  font-size: 0.9em;
}

span.aqua { color: aqua; }
span.black { color: black; }
span.blue { color: blue; }
span.fuchsia { color: fuchsia; }
span.gray { color: gray; }
span.green { color: green; }
span.lime { color: lime; }
span.maroon { color: maroon; }
span.navy { color: navy; }
span.olive { color: olive; }
span.purple { color: purple; }
span.red { color: red; }
span.silver { color: silver; }
span.teal { color: teal; }
span.white { color: white; }
span.yellow { color: yellow; }

span.aqua-background { background: aqua; }
span.black-background { background: black; }
span.blue-background { background: blue; }
span.fuchsia-background { background: fuchsia; }
span.gray-background { background: gray; }
span.green-background { background: green; }
span.lime-background { background: lime; }
span.maroon-background { background: maroon; }
span.navy-background { background: navy; }
span.olive-background { background: olive; }
span.purple-background { background: purple; }
span.red-background { background: red; }
span.silver-background { background: silver; }
span.teal-background { background: teal; }
span.white-background { background: white; }
span.yellow-background { background: yellow; }

span.big { font-size: 2em; }
span.small { font-size: 0.6em; }

span.underline { text-decoration: underline; }
span.overline { text-decoration: overline; }
span.line-through { text-decoration: line-through; }


/*
 * xhtml11 specific
 *
 * */

tt {
  font-family: monospace;
  font-size: inherit;
  color: navy;
}

div.tableblock {
  margin-top: 1.0em;
  margin-bottom: 1.5em;
}
div.tableblock > table {
  border: 3px solid #527bbd;
}
thead, p.table.header {
  font-weight: bold;
  color: #527bbd;
}
p.table {
  margin-top: 0;
}
/* Because the table frame attribute is overriden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
  border-style: none;
}
div.tableblock > table[frame="hsides"] {
  border-left-style: none;
  border-right-style: none;
}
div.tableblock > table[frame="vsides"] {
  border-top-style: none;
  border-bottom-style: none;
}


/*
 * html5 specific
 *
 * */

.monospaced {
  font-family: monospace;
  font-size: inherit;
  color: navy;
}

table.tableblock {
  margin-top: 1.0em;
  margin-bottom: 1.5em;
}
thead, p.tableblock.header {
  font-weight: bold;
  color: #527bbd;
}
p.tableblock {
  margin-top: 0;
}
table.tableblock {
  border-width: 3px;
  border-spacing: 0px;
  border-style: solid;
  border-color: #527bbd;
  border-collapse: collapse;
}
th.tableblock, td.tableblock {
  border-width: 1px;
  padding: 4px;
  border-style: solid;
  border-color: #527bbd;
}

table.tableblock.frame-topbot {
  border-left-style: hidden;
  border-right-style: hidden;
}
table.tableblock.frame-sides {
  border-top-style: hidden;
  border-bottom-style: hidden;
}
table.tableblock.frame-none {
  border-style: hidden;
}

th.tableblock.halign-left, td.tableblock.halign-left {
  text-align: left;
}
th.tableblock.halign-center, td.tableblock.halign-center {
  text-align: center;
}
th.tableblock.halign-right, td.tableblock.halign-right {
  text-align: right;
}

th.tableblock.valign-top, td.tableblock.valign-top {
  vertical-align: top;
}
th.tableblock.valign-middle, td.tableblock.valign-middle {
  vertical-align: middle;
}
th.tableblock.valign-bottom, td.tableblock.valign-bottom {
  vertical-align: bottom;
}
</style>
<script type="text/javascript">
/*<![CDATA[*/
var asciidoc = {  // Namespace.

/////////////////////////////////////////////////////////////////////
// Table Of Contents generator
/////////////////////////////////////////////////////////////////////

/* Author: Mihai Bazon, September 2002
 * http://students.infoiasi.ro/~mishoo
 *
 * Table Of Content generator
 * Version: 0.4
 *
 * Feel free to use this script under the terms of the GNU General Public
 * License, as long as you do not remove or alter this notice.
 */

 /* modified by Troy D. Hanson, September 2006. License: GPL */
 /* modified by Stuart Rackham, 2006, 2009. License: GPL */

// toclevels = 1..4.
toc: function (toclevels) {

  function getText(el) {
    var text = "";
    for (var i = el.firstChild; i != null; i = i.nextSibling) {
      if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
        text += i.data;
      else if (i.firstChild != null)
        text += getText(i);
    }
    return text;
  }

  function TocEntry(el, text, toclevel) {
    this.element = el;
    this.text = text;
    this.toclevel = toclevel;
  }

  function tocEntries(el, toclevels) {
    var result = new Array;
    var re = new RegExp('[hH]([2-'+(toclevels+1)+'])');
    // Function that scans the DOM tree for header elements (the DOM2
    // nodeIterator API would be a better technique but not supported by all
    // browsers).
    var iterate = function (el) {
      for (var i = el.firstChild; i != null; i = i.nextSibling) {
        if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
          var mo = re.exec(i.tagName);
          if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
            result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
          }
          iterate(i);
        }
      }
    }
    iterate(el);
    return result;
  }

  var toc = document.getElementById("toc");
  if (!toc) {
    return;
  }

  // Delete existing TOC entries in case we're reloading the TOC.
  var tocEntriesToRemove = [];
  var i;
  for (i = 0; i < toc.childNodes.length; i++) {
    var entry = toc.childNodes[i];
    if (entry.nodeName == 'DIV'
     && entry.getAttribute("class")
     && entry.getAttribute("class").match(/^toclevel/))
      tocEntriesToRemove.push(entry);
  }
  for (i = 0; i < tocEntriesToRemove.length; i++) {
    toc.removeChild(tocEntriesToRemove[i]);
  }

  // Rebuild TOC entries.
  var entries = tocEntries(document.getElementById("content"), toclevels);
  for (var i = 0; i < entries.length; ++i) {
    var entry = entries[i];
    if (entry.element.id == "")
      entry.element.id = "_toc_" + i;
    var a = document.createElement("a");
    a.href = "#" + entry.element.id;
    a.appendChild(document.createTextNode(entry.text));
    var div = document.createElement("div");
    div.appendChild(a);
    div.className = "toclevel" + entry.toclevel;
    toc.appendChild(div);
  }
  if (entries.length == 0)
    toc.parentNode.removeChild(toc);
},


/////////////////////////////////////////////////////////////////////
// Footnotes generator
/////////////////////////////////////////////////////////////////////

/* Based on footnote generation code from:
 * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
 */

footnotes: function () {
  // Delete existing footnote entries in case we're reloading the footnodes.
  var i;
  var noteholder = document.getElementById("footnotes");
  if (!noteholder) {
    return;
  }
  var entriesToRemove = [];
  for (i = 0; i < noteholder.childNodes.length; i++) {
    var entry = noteholder.childNodes[i];
    if (entry.nodeName == 'DIV' && entry.getAttribute("class") == "footnote")
      entriesToRemove.push(entry);
  }
  for (i = 0; i < entriesToRemove.length; i++) {
    noteholder.removeChild(entriesToRemove[i]);
  }

  // Rebuild footnote entries.
  var cont = document.getElementById("content");
  var spans = cont.getElementsByTagName("span");
  var refs = {};
  var n = 0;
  for (i=0; i<spans.length; i++) {
    if (spans[i].className == "footnote") {
      n++;
      var note = spans[i].getAttribute("data-note");
      if (!note) {
        // Use [\s\S] in place of . so multi-line matches work.
        // Because JavaScript has no s (dotall) regex flag.
        note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
        spans[i].innerHTML =
          "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
          "' title='View footnote' class='footnote'>" + n + "</a>]";
        spans[i].setAttribute("data-note", note);
      }
      noteholder.innerHTML +=
        "<div class='footnote' id='_footnote_" + n + "'>" +
        "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
        n + "</a>. " + note + "</div>";
      var id =spans[i].getAttribute("id");
      if (id != null) refs["#"+id] = n;
    }
  }
  if (n == 0)
    noteholder.parentNode.removeChild(noteholder);
  else {
    // Process footnoterefs.
    for (i=0; i<spans.length; i++) {
      if (spans[i].className == "footnoteref") {
        var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
        href = href.match(/#.*/)[0];  // Because IE return full URL.
        n = refs[href];
        spans[i].innerHTML =
          "[<a href='#_footnote_" + n +
          "' title='View footnote' class='footnote'>" + n + "</a>]";
      }
    }
  }
},

install: function(toclevels) {
  var timerId;

  function reinstall() {
    asciidoc.footnotes();
    if (toclevels) {
      asciidoc.toc(toclevels);
    }
  }

  function reinstallAndRemoveTimer() {
    clearInterval(timerId);
    reinstall();
  }

  timerId = setInterval(reinstall, 500);
  if (document.addEventListener)
    document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);
  else
    window.onload = reinstallAndRemoveTimer;
}

}
asciidoc.install();
/*]]>*/
</script>
</head>
<body class="article">
<div id="header">
<h1>Listing of doc/example-scripts/per-object-mixins.tcl</h1>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<div class="paragraph"><p>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.</p></div>
<div class="listingblock">
<div class="content"><style type='text/css'>
.nx             {color: #000000; font-weight: normal; font-style: normal; padding-left: 10px}
table.nx        {border-collapse: collapse; border-spacing: 3px;}
.nx-linenr      {border-right: 1px solid #DDDDDD;padding-right: 5px; color: #2B547D;font-style: italic;}
.nx-string      {color: #779977; font-weight: normal; font-style: italic;}
.nx-comment     {color: #717ab3; font-weight: normal; font-style: italic;}
.nx-keyword     {color: #7f0055; font-weight: normal; font-style: normal;}
.nx-placeholder {color: #AF663F; font-weight: normal; font-style: italic;}
.nx-variable    {color: #AF663F; font-weight: normal; font-style: normal;}
</style>
<pre class='nx'><span class='nx-keyword'>package</span> req nx</pre></div></div>
<div class="paragraph"><p>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.</p></div>
<div class="listingblock">
<div class="content"><style type='text/css'>
.nx             {color: #000000; font-weight: normal; font-style: normal; padding-left: 10px}
table.nx        {border-collapse: collapse; border-spacing: 3px;}
.nx-linenr      {border-right: 1px solid #DDDDDD;padding-right: 5px; color: #2B547D;font-style: italic;}
.nx-string      {color: #779977; font-weight: normal; font-style: italic;}
.nx-comment     {color: #717ab3; font-weight: normal; font-style: italic;}
.nx-keyword     {color: #7f0055; font-weight: normal; font-style: normal;}
.nx-placeholder {color: #AF663F; font-weight: normal; font-style: italic;}
.nx-variable    {color: #AF663F; font-weight: normal; font-style: normal;}
</style>
<pre class='nx'><span class='nx-keyword'>nx::Class</span> <span class='nx-keyword'>create</span> BaseClass {
  :<span class='nx-keyword'>public</span> <span class='nx-keyword'>method</span> speak {} {
    <span class='nx-keyword'>puts</span> <span class='nx-string'>"Hello from BC."</span>
  }
}

<span class='nx-keyword'>nx::Class</span> <span class='nx-keyword'>create</span> DerivedClass -<span class='nx-keyword'>superclass</span> BaseClass {
  :<span class='nx-keyword'>public</span> <span class='nx-keyword'>method</span> speak {} {
    <span class='nx-keyword'>next</span>
    <span class='nx-keyword'>puts</span> <span class='nx-string'>"Hello from DC."</span>
  }
}

DerivedClass <span class='nx-keyword'>create</span> o1
o1 speak</pre></div></div>
<div class="paragraph"><p>The output is:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>   Hello from BC.
   Hello from DC.</tt></pre>
</div></div>
<div class="paragraph"><p>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.</p></div>
<div class="listingblock">
<div class="content"><style type='text/css'>
.nx             {color: #000000; font-weight: normal; font-style: normal; padding-left: 10px}
table.nx        {border-collapse: collapse; border-spacing: 3px;}
.nx-linenr      {border-right: 1px solid #DDDDDD;padding-right: 5px; color: #2B547D;font-style: italic;}
.nx-string      {color: #779977; font-weight: normal; font-style: italic;}
.nx-comment     {color: #717ab3; font-weight: normal; font-style: italic;}
.nx-keyword     {color: #7f0055; font-weight: normal; font-style: normal;}
.nx-placeholder {color: #AF663F; font-weight: normal; font-style: italic;}
.nx-variable    {color: #AF663F; font-weight: normal; font-style: normal;}
</style>
<pre class='nx'>BaseClass <span class='nx-keyword'>method</span> unknown {m args} {
  <span class='nx-keyword'>puts</span> <span class='nx-string'>"What? $m? I don't understand."</span>
}
o1 sing</pre></div></div>
<div class="paragraph"><p>The output is:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>    What? sing? I don't understand.</tt></pre>
</div></div>
<div class="paragraph"><p>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:</p></div>
<div class="listingblock">
<div class="content"><style type='text/css'>
.nx             {color: #000000; font-weight: normal; font-style: normal; padding-left: 10px}
table.nx        {border-collapse: collapse; border-spacing: 3px;}
.nx-linenr      {border-right: 1px solid #DDDDDD;padding-right: 5px; color: #2B547D;font-style: italic;}
.nx-string      {color: #779977; font-weight: normal; font-style: italic;}
.nx-comment     {color: #717ab3; font-weight: normal; font-style: italic;}
.nx-keyword     {color: #7f0055; font-weight: normal; font-style: normal;}
.nx-placeholder {color: #AF663F; font-weight: normal; font-style: italic;}
.nx-variable    {color: #AF663F; font-weight: normal; font-style: normal;}
</style>
<pre class='nx'>o1 <span class='nx-keyword'>public</span> <span class='nx-keyword'>method</span> sing {} {
  <span class='nx-keyword'>puts</span> <span class='nx-string'>"Ok, here it goes: Lala Lala!"</span>
}
o1 sing</pre></div></div>
<div class="paragraph"><p>The output is:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>    Ok, here it goes: Lala Lala!</tt></pre>
</div></div>
<div class="paragraph"><p>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:</p></div>
<div class="listingblock">
<div class="content"><style type='text/css'>
.nx             {color: #000000; font-weight: normal; font-style: normal; padding-left: 10px}
table.nx        {border-collapse: collapse; border-spacing: 3px;}
.nx-linenr      {border-right: 1px solid #DDDDDD;padding-right: 5px; color: #2B547D;font-style: italic;}
.nx-string      {color: #779977; font-weight: normal; font-style: italic;}
.nx-comment     {color: #717ab3; font-weight: normal; font-style: italic;}
.nx-keyword     {color: #7f0055; font-weight: normal; font-style: normal;}
.nx-placeholder {color: #AF663F; font-weight: normal; font-style: italic;}
.nx-variable    {color: #AF663F; font-weight: normal; font-style: normal;}
</style>
<pre class='nx'><span class='nx-keyword'>nx::Class</span> <span class='nx-keyword'>create</span> M {
  :<span class='nx-keyword'>public</span> <span class='nx-keyword'>method</span> sing {} {
    <span class='nx-keyword'>puts</span> -nonewline <span class='nx-string'>"[self] sings: "</span>
    <span class='nx-keyword'>next</span>
  }
  :<span class='nx-keyword'>method</span> unknown args {
    <span class='nx-keyword'>puts</span> -nonewline <span class='nx-string'>"[self] is confused: "</span>
    <span class='nx-keyword'>next</span>
  }
}</pre></div></div>
<div class="paragraph"><p>The behavior of M can be mixed into the behavior of o1 through
per object mixins &#8230;</p></div>
<div class="listingblock">
<div class="content"><style type='text/css'>
.nx             {color: #000000; font-weight: normal; font-style: normal; padding-left: 10px}
table.nx        {border-collapse: collapse; border-spacing: 3px;}
.nx-linenr      {border-right: 1px solid #DDDDDD;padding-right: 5px; color: #2B547D;font-style: italic;}
.nx-string      {color: #779977; font-weight: normal; font-style: italic;}
.nx-comment     {color: #717ab3; font-weight: normal; font-style: italic;}
.nx-keyword     {color: #7f0055; font-weight: normal; font-style: normal;}
.nx-placeholder {color: #AF663F; font-weight: normal; font-style: italic;}
.nx-variable    {color: #AF663F; font-weight: normal; font-style: normal;}
</style>
<pre class='nx'>o1 <span class='nx-keyword'>mixin</span> M</pre></div></div>
<div class="olist lowerroman"><ol class="lowerroman">
<li>
<p>
and we call the methods again:
</p>
</li>
</ol></div>
<div class="listingblock">
<div class="content"><style type='text/css'>
.nx             {color: #000000; font-weight: normal; font-style: normal; padding-left: 10px}
table.nx        {border-collapse: collapse; border-spacing: 3px;}
.nx-linenr      {border-right: 1px solid #DDDDDD;padding-right: 5px; color: #2B547D;font-style: italic;}
.nx-string      {color: #779977; font-weight: normal; font-style: italic;}
.nx-comment     {color: #717ab3; font-weight: normal; font-style: italic;}
.nx-keyword     {color: #7f0055; font-weight: normal; font-style: normal;}
.nx-placeholder {color: #AF663F; font-weight: normal; font-style: italic;}
.nx-variable    {color: #AF663F; font-weight: normal; font-style: normal;}
</style>
<pre class='nx'>o1 sing
o1 <span class='nx-keyword'>read</span></pre></div></div>
<div class="paragraph"><p>The output is:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>   ::o1 sings: Ok, here it goes: Lala Lala!
   ::o1 is confused: What? read? I don't understand.</tt></pre>
</div></div>
<div class="paragraph"><p>We can remove the new behavior easily by unregistering the
mixin class &#8230;.</p></div>
<div class="listingblock">
<div class="content"><style type='text/css'>
.nx             {color: #000000; font-weight: normal; font-style: normal; padding-left: 10px}
table.nx        {border-collapse: collapse; border-spacing: 3px;}
.nx-linenr      {border-right: 1px solid #DDDDDD;padding-right: 5px; color: #2B547D;font-style: italic;}
.nx-string      {color: #779977; font-weight: normal; font-style: italic;}
.nx-comment     {color: #717ab3; font-weight: normal; font-style: italic;}
.nx-keyword     {color: #7f0055; font-weight: normal; font-style: normal;}
.nx-placeholder {color: #AF663F; font-weight: normal; font-style: italic;}
.nx-variable    {color: #AF663F; font-weight: normal; font-style: normal;}
</style>
<pre class='nx'>o1 <span class='nx-keyword'>mixin</span> <span class='nx-string'>""</span></pre></div></div>
<div class="olist lowerroman"><ol class="lowerroman">
<li>
<p>
and we call the methods again:
</p>
</li>
</ol></div>
<div class="listingblock">
<div class="content"><style type='text/css'>
.nx             {color: #000000; font-weight: normal; font-style: normal; padding-left: 10px}
table.nx        {border-collapse: collapse; border-spacing: 3px;}
.nx-linenr      {border-right: 1px solid #DDDDDD;padding-right: 5px; color: #2B547D;font-style: italic;}
.nx-string      {color: #779977; font-weight: normal; font-style: italic;}
.nx-comment     {color: #717ab3; font-weight: normal; font-style: italic;}
.nx-keyword     {color: #7f0055; font-weight: normal; font-style: normal;}
.nx-placeholder {color: #AF663F; font-weight: normal; font-style: italic;}
.nx-variable    {color: #AF663F; font-weight: normal; font-style: normal;}
</style>
<pre class='nx'>o1 sing
o1 <span class='nx-keyword'>read</span></pre></div></div>
<div class="paragraph"><p>The output is:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>   Ok, here it goes: Lala Lala!
   What? read? I don't understand.</tt></pre>
</div></div>
<div class="paragraph"><p>Mixin classes can be used to extend the behavior of classes
as well.</p></div>
<div class="listingblock">
<div class="content"><style type='text/css'>
.nx             {color: #000000; font-weight: normal; font-style: normal; padding-left: 10px}
table.nx        {border-collapse: collapse; border-spacing: 3px;}
.nx-linenr      {border-right: 1px solid #DDDDDD;padding-right: 5px; color: #2B547D;font-style: italic;}
.nx-string      {color: #779977; font-weight: normal; font-style: italic;}
.nx-comment     {color: #717ab3; font-weight: normal; font-style: italic;}
.nx-keyword     {color: #7f0055; font-weight: normal; font-style: normal;}
.nx-placeholder {color: #AF663F; font-weight: normal; font-style: italic;}
.nx-variable    {color: #AF663F; font-weight: normal; font-style: normal;}
</style>
<pre class='nx'>BaseClass <span class='nx-keyword'>mixin</span> M

o1 sing
o1 <span class='nx-keyword'>read</span>

DerivedClass <span class='nx-keyword'>create</span> o2
o2 <span class='nx-keyword'>read</span></pre></div></div>
<div class="paragraph"><p>The output is:</p></div>
<div class="listingblock">
<div class="content">
<pre><tt>   ::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.</tt></pre>
</div></div>
</div>
</div>
</div>
<div id="footnotes"><hr /></div>
<div id="footer">
<div id="footer-text">
Last updated 2011-09-19 03:46:57 CEST
</div>
</div>
</body>
</html>