    [NAME]
    ALL.dao.tutorial.class

    [TITLE]
    Class, Mixin, OOP and AOP

    [DESCRIPTION]

    Object-Oriented Programming (OOP) is supported in Dao by offering class-based features
    such as data abstraction, encapsulation, polymorphism and inheritance etc. And such
    support for OOP is further enhanced by interface.

     0.1  Class Definition

    A class is a user-defined data structure consisting data fields and member methods,
    which define the states and behaviours for the instances of the class. Class supports
    three types of fields:
      *  constant: declared with keyword const;
      *  static variable: declared with keyword static;
      *  instance variable: declared with keyword var;
    Such fields can be declared with or without explicit types, and with or without default
    or initialization values, in the same way as specifying types and/or default values for
    function parameters. For example, the following can be used for instance variables,

       1  var variable;
       2  var variable = init_value;
       3  var variable : typename;
       4  var variable : typename = init_value;

    Class methods must be declared with keyword routine (or its alias keywords function or
    sub) for constructors and normal methods, or keyword operator for operator overloading.

    The access of class fields and methods can be restricted by three permission keywords:
      *  public: publically accessible without restriction;
      *  protected: accessible from the class and its derived classes;
      *  private: only accessible from the class;

    Here is a simple class,

       1  class ClassOne
       2  {
       3      var index = 0;
       4      var name  : string
       5      var words : list<string> = {}
       6
       7      routine ClassOne( name :string, index = 0 ){
       8          self.name = name;
       9          self.index = index;
      10      }
      11  }

    Within class methods, the special variable self represents the current class instance.
    Class methods may be declared inside class body and defined outside in the same way as in
    C++, but in Dao, one should make sure that, the parameter list must be exactly the same
    in the places for declaration and definition.

     0.2  Class Instance

    Class constructors are the methods that have name the same as the class name. A class
    instance can be created by invoking a constructor of the class in the same way as a
    function call,

       1  object = ClassOne( 'abc' )

    Like in Python, the constructors are not used to create class instances, instead, an
    instance is created before, and then the constructor is called after to initialize the
    instance.

    For a class without parent classes and without constructors, its instances may also be
    created by enumerating the members of the class,

       1  class Point3D
       2  {
       3      var x = 0D;
       4      var y = 0D;
       5      var z = 0D;
       6  }
       7  point = Point3D::{ 1, 2, 3 };

    The names of instance variables may also be specified in enumeration,

       1  point = Point3D::{
       2      y => 2,
       3      x => 1,
       4      z => 3,
       5  };

    When you create a class instance using enumeration, the instance is created, and filled
    with the values in the enumeration. Instance creation by enumeration is much faster than
    creation by invoking class constructor, since no class constructor is called and there is
    no overhead associated with function call (parameter passing, running time context
    preparation for the call etc.). So such instance creation is very desirable for creating
    many instances for simple classes, in which there are no complicated initialization
    operations.

     0.3  Member Variable

    As mentioned above, instance variables are declared in class constructor using var
    keyword. Class constant can be declared using const keyword, and static member can be
    declared using static keyword as in C++:

       1  class Klass
       2  {
       3      const aClassConst = "KlassConst";
       4      static aClassStatic;
       5  }

    Here aClassConst will be constant belonging to a Klass. While aClassStatic will be a
    static variable in the class scope.

     0.4  Setters, Getters and Overloadable Operators

    Instead of defining setXyz() methods, one can define .Xyz=() method as setter operator,
    so that modifying class member Xyz by obj.Xyz=abc will be allowed; similarly, if .Xyz()
    is defined, get the value by obj.Xyz will also be allowed:

       1  class MyNumber
       2  {
       3      private
       4
       5      var value = 0;
       6
       7      public
       8
       9      routine MyNumber( v = 0 ){
      10          value = v;
      11      }
      12
      13      operator .value=( v ){ value = v; io.writeln( "value is set" ) }
      14      operator .value(){ return value }
      15  }
      16
      17  num = MyNumber( 123 )
      18  num.value = 456
      19  io.writeln( num.value )

    As you may guess, accessing instance variable through getters and setters are more
    expensive than using them as public variables! They should be used only when they make
    things more convenient (for example, when you want them to do extra work when a variable
    is accessed).

    Other supported operators for overloaing include:
      1. [operator ()(...)] for function call;
      2. [operator [](...)] for getting item(s);
      3. [operator []=(...)] for setting item(s);
    Basic arithmetic operators are also supported for overloading.

     0.5  Method Overloading

    Class methods can be overloaded in the same way as normal functions. Class constructor
    may also be overloaded by simply adding a method with the same name as the class. For
    example, class MyNumber can be modified to hold numeric value only:

       1  class MyNumber
       2  {
       3      private
       4
       5      var value : int = 0;
       6
       7      public
       8
       9      routine MyNumber( value = 0 ){ # accept integer as parameter
      10          self.value = value;
      11      }
      12
      13      # overloaded constructor to accept MyNumber as parameter:
      14      routine MyNumber( value : MyNumber ){ self.value = value.value }
      15
      16      operator .value=( v : int ){ value = v }
      17      operator .value=( v : MyNumber ){ value = v.value }
      18      operator .value(){ return value }
      19  }
      20
      21  num1 = MyNumber( 123 )
      22  num1.value = 456
      23  io.writeln( num1.value )
      24
      25  num2 = MyNumber( num1 )
      26  io.writeln( num2.value )
      27
      28  num2.value = 789
      29  io.writeln( num2.value )
      30
      31  num2.value = num1
      32  io.writeln( num2.value )

     0.6  Inheritance

       1  class ColorRBG
       2  {
       3      var Red = 0.0;
       4      var Green = 0.0;
       5      var Blue = 0.0;
       6
       7      routine ColorRBG( r = 0.0, g = 0.0, b = 0.0 ){
       8          Red = r;
       9          Green = g;
      10          Blue = b;
      11      }
      12      routine ColorRGB( name : enum<white,black,red,green,blue,yellow,magenta,cyan> ){
      13          switch( name ){
      14          case $white:   Red = Green = Blue = 1.0
      15          case $black:
      16          case $red:     Red = 1.0
      17          case $green:   Green = 1.0
      18          case $blue:    Blue = 1.0
      19          case $yellow:  Red = Green = 1.0
      20          case $magenta: Red = Blue = 1.0
      21          case $cyan:    Green = Blue = 1.0
      22          }
      23      }
      24
      25      routine setRed( r ){ Red = r; }
      26      routine setGreen( g ){ Green = g; }
      27      routine setBlue( b ){ Blue = b; }
      28
      29      routine getRed(){ return Red; }
      30      routine getGreen(){ return Green; }
      31      routine getBlue(){ return Blue; }
      32  }
      33
      34  yellow = ColorRBG( 1, 1, 0 ); # create an instance.

    The following will define a derived class of ColorRBG,

       1  class ColorRGBA : ColorRBG
       2  {
       3      var alpha = 0.0; # alpha component for tranparency.
       4
       5      routine ColorRGBA( r = 0.0, g = 0.0, b = 0.0, a = 0.0 ) : ColorRBG( r, g, b ){
       6          alpha = a;
       7      }
       8      # Inherit the constructor from ColorRGB that accepts color names:
       9      use routine ColorRGB( name : enum<white,black,red,green,blue,yellow,magenta,cyan> );
      10  }
      11
      12  yellow2 = ColorRGBA( 1, 1, 0, 0 ); # not tranparent.
      13  yellow2.alpha = 0.5; # change to half tranparency.
      14
      15  magenta = ColorRGBA( $magenta )

    In the definition of derived class, the parent class ColorRBG should be put after the
    derived class and be separated with :. <red>(Since 2013-10-20, classic multiple
    inheritance is no longer support. Now mixins are the preferred way to do similar
    things.)</red> The constructor parameters for derived class can be passed to parent
    classes in the way as shown in the example.

    Constructors from the parent class can be inherited by using the use statement, in which
    the full function signature of the constructor should be specified.

     0.7   Mixin

    Features introduced in the this and the remaining sections are available only in the
    latest devel release and the online version.

    Classes to be used as mixins can be specified in a pair of brackets following the class
    name. Only classes without parent classes can be used as mixins.

       1  class Base
       2  {
       3      var value = 456
       4      routine Meth2(){ io.writeln( self, value ) }
       5  }
       6
       7  class Mixin ( Base )
       8  {
       9      var index = 123
      10
      11      routine Meth(){ io.writeln( self, index, value ) }
      12      routine Meth2( a : string ){ io.writeln( self, index, value, a ) }
      13  }
      14
      15  #
      16  # The "Base" class will be presented only once in "Klass":
      17  #
      18  class Klass ( Base, Mixin )
      19  {
      20      var index = 123456
      21      routine Meth2( a : int ){ io.writeln( self, index, value, a ) }
      22  }
      23
      24  k = Klass()
      25
      26  io.writeln( k.index )
      27
      28  k.Meth()
      29  k.Meth2()
      30  k.Meth2( 'abc' )
      31  k.Meth2( 789 )

     0.8   Class Decorator

    (New in the latest devel release and online version)
    Class decorators are classes that can be used modify other classes. The modification is
    done by using such class as a mixin base class to inject (combine) its members into the
    modified class, and by automatically applying its method decorators to the methods of the
    modified class.
    For such auto decorator application, only decorators with explicitly specified decoration
    targets are automatically applied. Such targets are expressed as prefix and suffix rules
    which can be expressed in the following ways:
      1. Prefix~ : a prefix pattern. The decorator will be auto applied to methods that have
         names with such prefix;
      2. ~Suffix : a suffix pattern. The decorator will be auto applied to methods that have
         names with such suffix;
      3. Prefix~Suffix : a prefix and suffix pattern. The decorator will be auto applied to
         methods that have names with such prefix and suffix;
      4. ~ : an empty prefix and suffix pattern. The decorator will be auto applied to any
         methods.

    When multiple mixins are used in a host class, the decorators of the first mixin are
    applied the last. And the first decorator of the same decorator is also applied the last
    as well.

       1  class @Header
       2  {
       3      static routine @Delimiter( meth(args) : routine ) for ~ {
       4          io.writeln( '=======================' )
       5          return meth( args, ... )
       6      }
       7      routine @Delimiter( meth(args) : routine ) for ~ {
       8          io.writeln( '-----------------------' )
       9          return meth( args, ... )
      10      }
      11  }
      12  class @Decorator
      13  {
      14      var value = 654321
      15
      16      routine @Test( meth(args) :routine<self:@Decorator> ) for Test {
      17          io.writeln( 'Decorator::Test()', value )
      18          meth( args, ... );
      19      }
      20      routine @Prefix( meth(args) :routine<self:@Decorator> ) for Prefix~ {
      21          io.writeln( 'Decorator::Prefix()' )
      22          meth( args, ... );
      23      }
      24      routine @Suffix( meth(args) :routine<self:@Decorator> ) for ~Suffix {
      25          io.writeln( 'Decorator::Suffix()' )
      26          meth( args, ... );
      27      }
      28      routine @Prefix_Suffix( meth(args) :routine<self:@Decorator> ) for Prefix~Suffix {
      29          io.writeln( 'Decorator::Prefix_Suffix()' )
      30          meth( args, ... );
      31      }
      32  }
      33
      34  class MyMixin ( @Header, @Decorator )
      35  {
      36      routine Test(){
      37          io.writeln( 'MyMixin::Test()' )
      38      }
      39      routine PrefixTest(){
      40          io.writeln( 'MyMixin::PrefixTest()' )
      41      }
      42      routine TestSuffix(){
      43          io.writeln( 'MyMixin::TestSuffix()' )
      44      }
      45      routine PrefixTestSuffix(){
      46          io.writeln( 'MyMixin::PrefixTestSuffix()' )
      47      }
      48  }
      49
      50  obj = MyMixin()
      51  obj.Test()
      52  obj.PrefixTest()
      53  obj.TestSuffix()
      54  obj.PrefixTestSuffix()

     0.9   Aspect Class

    (New in the latest devel release and online version)

    In Dao, a class decorator can be effectly used as an aspect for AOP, if decoration target
    patterns are specified for auto application. The target patterns are can be specified in
    the same way as the target patterns for class method decorators.

    The fields of such class will be automatically injected to normal classes selected
    according to the affix rules, and the decorators defined in such aspect class are
    automatically applied to the methods (selected according to the same affix rules) of the
    normal classes.

       1  class @AspectForAnyClass for ~  # To be applied to any classes;
       2  {
       3      var injected : list<int> = {}
       4
       5      # This is not a decorator!
       6      routine @AspectForAnyClass(){
       7          io.writeln( 'In @AspectForAnyClass():' );
       8          injected = { 1, 2, 3 }
       9      }
      10
      11      # This decorator will also be applied to the default constructors:
      12      routine @DecoratorForAnyMethod( meth(args) : routine ) for ~ {
      13          io.writeln( 'In @DecoratorForAnyMethod():', std.about(meth) )
      14          io.writeln( injected )
      15          return meth( args, ... )
      16      }
      17  }
      18
      19  # For classes with names prefixed with My:
      20  class @AspectForMyClasses for My~
      21  {
      22      routine @Method( meth(args) : routine ) for Method~ {
      23          io.writeln( 'In @AspectForMyClasses::@Method():', std.about(meth) )
      24          return meth( args, ... )
      25      }
      26  }
      27
      28  class MyClass
      29  {
      30      routine Method(){ io.writeln( 'MyClass::Method()' ) }
      31  }
      32
      33  k = MyClass()  # Invoke the default constructor of Klass;
      34  k.Method()