load help;

@[name]
dao.class
@[name]

@[title]
Class for Object-Oriented Programming
@[title]


@[text]
A @[green]class@[green] is a user-defined data structure consisting data fields and
member methods, which define the states and behaviours for the instances of the class.
It is one of the basic building blocks for object-orient programming.
@[text]




@[name]
dao.class.definition
@[name]

@[title]
Definition
@[title]


@[text]
Classes are defined using the @[green]class@[green] keyword, followed
by a class name and base/parent classes if any, and then the class body.
The following is the simplest class:
@[code]
class SimplestClass
{
}
@[code]
which has no base classes and contains no member fields.
In order for the class to have meaningful use,
it must contains some fields to define the states or behavior
of the class or its instance.


@[subsection]
Member Data Field
@[subsection]


Class supports three types data of fields:
@[list]
--@[green]constant@[green]: declared with keyword @[green]const@[green];
--@[green]static variable@[green]: declared with keyword @[green]static@[green];
--@[green]instance variable@[green]: declared with keyword @[green]var@[green];
@[list]
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,
@[code]
var variable;
var variable = init_value;
var variable : typename;
var variable : typename = init_value;
@[code]


@[subsection]
Member Method Field
@[subsection]

Dao class supports multiple type of member methods such as
constructor, static method, instance method and
methods for overloaded operators.


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


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


@[subsection]
Class Instance
@[subsection]

The following is a simple class without a constructor:
@[code]
class Contact
{
	const description = 'This is a class for contact information'
	var   name = 'Nobody'
	var   address = 'Nowhere'

	routine Show(){ io.writeln( name, 'lives at', address ) }
}
@[code]
There are two ways to create instances of such simple classes:
@[list]
-- Call the default constructor which will initialize the instance variables
   with their default values:
   @[code]
   obj = Contact()
   @[code]
-- Enumerate the values of the instance variables:
   @[code]
   obj = Contact{ 'Mike', '123 Main Street' }
   @[code]
   Field names can be specified for the values, so that these values can appear
   in arbitrary order:
   @[code]
   obj = Contact{ address => '123 Main Street', name => 'Mike' }
   @[code]
   Please note, only simple classes without base classes and explicit constructors
   can use this kind of instance construction.
@[list]



@[subsection]
Class Constructor
@[subsection]

In a class, the methods with the same name as the class itself
are considerred as class constructors.
When the class name is used for a function call,
a class instance will be created and then the appropriate constructor
will be invoked to initialize the instance.
Here is the same class as above, but with a constructor:
@[code]
class Contact
{
	const description = 'This is a class for contact information'
	var   name = 'Nobody'
	var   address = 'Nowhere'

	routine Contact( name : string, address = 'Unknown' ){
		self.name = name
		self.address = address
	}

	routine Show(){ io.writeln( name, 'lives at', address ) }
}
@[code]
Now calling the constructor is the only way to create 
an instance of @[green]Contact@[green]:
@[code]
obj = Contact( 'Mike', '123 Main Street' )
@[code]


Class constructors can be overloaded in the same way as normal functions:
@[code]
class Contact
{
	const description = 'This is a class for contact information'
	var   name = 'Nobody'
	var   address = 'Nowhere'

	routine Contact( name : string, address = 'Unknown' ){
		self.name = name
		self.address = address
	}
	routine Contact( another : Contact ){
		name = another.name
		address = another.address
	}

	routine Show(){ io.writeln( name, 'lives at', address ) }
}
@[code]


@[subsection]
Static Method
@[subsection]

Static methods can be defined by specifying the @[green]static@[green] keyword
before the @[green]routine@[green] keyword.
Such method can be invoked without class instance, for this, they are not allowed
to use class instance variables.
@[code]
class Klass
{
	var id = 123
	static info = 'Klass'
	static routine StaticMethod(){ id = 1 }  # Wrong;
	static routine StaticMethod(){ io.writeln( info ) }  # Correct;
}
obj = Klass::StaticMethod()
@[code]



@[text]




@[name]
dao.class.inheritance
@[name]

@[title]
Inheritance
@[title]


@[text]

In Dao, new classes can be derived from existing classes (and/or C data types)
to inherit their functionalities and to establish is-a relationship between objects.
When a class A is derived from another class B, class A is usually referred to as
a child, or derived, or sub- class, and the class B is ussually referred to as
a parent or base class.


To derive one class from another, the base class must be placed after
the class name of the derived one separated by a colon.
<red>(Since 2013-10-20, classic multiple inheritance is no longer support.
Now mixins are the preferred way to do similar things.)</red>


Here is a simple example,
@[code]
class Base
{
	var id = 0

	routine Base( i = 0 ){ id = i }
}
class Sub : Base
{
	var value = 'abc'
}
obj = Sub()
@[code]
In this example, an instance of the derived class is created by calling its
implicit default constructor, which will call an constructor (either implicit
or explicit) of the derived class that accepts no parameters.


When defining a constructor of a derived class, the constructor of a base
class can be called explicitly, by placing the call right after
the constructor signature of the derived on separated by a colon.
The call to a base constructor can only accept the parameters 
(or the @[green]self@[green] variable) of 
the constructor of the derived class.
@[code]
class Sub : Base
{
	var value = 'abc'

	routine Sub( v = 'ABC', i = 3 ) : Base( i ) { value = v }
}
@[code]


@[code]
load meta

class Base
{
	var id = 0

	routine VirtMeth(){ io.writeln( 'Base::VirtMeth()' ) }
	routine NormMeth(){
		meta.self( self ).VirtMeth() # emulate virtual method call;
	}
}
class Sub : Base
{
	var value = 'abc'
	routine VirtMeth(){ io.writeln( 'Sub::VirtMeth()' ) }
}
o : Base = Sub()
o.NormMeth() # prints: Sub::VirtMeth()
@[code]


@[text]






@[name]
dao.class.operator
@[name]

@[title]
Operator Overloading
@[title]


@[text]

Class instances can be used in operations in a way similar to those
of built-in types, if the classes define methods to overload relevant operators.


Basic arithmetic operators are also supported for overloading.
For example, addition operator can be supported for a class by defining
a @[green]operator+@[green] method in the following class,
@[code]
class Integer
{
	var value = 0

	routine Integer( val = 0 ){ value = val }

	static operator +( A : Integer, B : Integer ){
		io.writeln( 'Integer + Integer' );
		return Integer( A.value + B.value );
	}
}
I1 = Integer( 123 )
I2 = Integer( 456 )
I3 = I1 + I2
@[code]

Operation for accessing member fields can also be redefined
as overloaded operator @[green]operator .field_name@[green]
and @[green]operator .field_name=@[green]:
@[code]
class Integer
{
	private
	var value = 0

	public
	routine Integer( val = 0 ){ value = val }

	operator .value(){ io.writeln( 'get value' ) }
	operator .value=( v : int ){ value = v; io.writeln( 'get value' ) }
}
I = Integer( 123 )
v = I.value
I.value = 456
@[code]


Some classes may behavior like containers and have members
that can be accessed using an index or a key.
To support member accessing using an index or key,
such class can overload operator @[green][]@[green] and @[green][]=@[green]
@[code]
class IntList
{
	var ints = {}

	routine Append( value : int ){ ints.append( value ) }
	operator []( index : int ){ return ints[index] }
	operator []=( value :int, index : int ){ ints[index] = value }
}
ilist = IntList()
ilist.Append( 123 )
ilist.Append( 456 )
ilist[0] = 789
io.writeln( ilist[0] )
@[code]


TODO: cast

@[text]


#{
In order to avoid creating new class instance whenever such addition operation
is performed, one can define another addition method that can be used when
the instance created by this operation is a temporary object and can be reused.
This method will take the reusable temporary object as the first parameter,
@[code]
class Integer
{
	var value = 0

	routine Integer( val = 0 ){ value = val }

	static operator +( A : Integer, B : Integer ){
		io.writeln( 'Integer + Integer' );
		return Integer( A.value + B.value );
	}
	static operator +( C : Integer, A : Integer, B : Integer ){
		io.writeln( 'Integer = Integer + Integer' );
		C.value = A.value + B.value;
		return C;
	}
}
I1 = Integer( 123 )
I2 = Integer( 456 )
for( i = 1 : 3 ) I3 = I1 + I2
@[code]
#}






@[name]
dao.class.mixin
@[name]

@[title]
Mixin Class
@[title]


@[text]


Classes to be used as mixin bases (components) can be specified in
a pair of brackets following the class name.
Only classes without parent classes can be used as mixin bases.

@[code]
class Base
{
	var value = 456
	routine Meth2(){ io.writeln( self, value ) }
}

class Mixin ( Base )
{
	var index = 123

	routine Meth(){ io.writeln( self, index, value ) }
	routine Meth2( a : string ){ io.writeln( self, index, value, a ) }
}

#
# The "Base" class will be presented only once in "Klass":
#
class Klass ( Base, Mixin )
{
	var index = 123456
	routine Meth2( a : int ){ io.writeln( self, index, value, a ) }
}

k = Klass()

io.writeln( k.index )

k.Meth()
k.Meth2()
k.Meth2( 'abc' )
k.Meth2( 789 )
@[code]

@[text]






@[name]
dao.class.decorator
@[name]

@[title]
Class Decorator
@[title]


@[text]


Class decorators are classes (prefixed with @[green]@@[green])
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 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:
@[list]
-- @[green]Prefix~@[green] : a prefix pattern.

   The decorator will be auto applied to methods that have names
   with such prefix;

-- @[green]~Suffix@[green] : a suffix pattern.

   The decorator will be auto applied to methods that have names
   with such suffix;

-- @[green]Prefix~Suffix@[green] : a prefix and suffix pattern.

   The decorator will be auto applied to methods that have names
   with such prefix and suffix;

-- @[green]~@[green] : an empty prefix and suffix pattern.

   The decorator will be auto applied to any methods.
@[list]



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

@[code]
class @Header
{
    static routine @Delimiter( meth(args) : routine ) for ~ { 
        io.writeln( '=======================' )
        return meth( args, ... )
    }   
    routine @Delimiter( meth(args) : routine ) for ~ { 
        io.writeln( '-----------------------' )
        return meth( args, ... )
    }   
}
class @Decorator
{
    var value = 654321

    routine @Test( meth(args) : routine<self:@Decorator> ) for Test {
        io.writeln( 'Decorator::Test()', value )
        meth( args, ... );
    }   
    routine @Prefix( meth(args) : routine<self:@Decorator> ) for Prefix~ {
        io.writeln( 'Decorator::Prefix()' )
        meth( args, ... );
    }
    routine @Suffix( meth(args) : routine<self:@Decorator> ) for ~Suffix {
        io.writeln( 'Decorator::Suffix()' )
        meth( args, ... );
    }
    routine @Prefix_Suffix( meth(args) : routine<self:@Decorator> ) for Prefix~Suffix {
        io.writeln( 'Decorator::Prefix_Suffix()' )
        meth( args, ... );
    }
}

class MyMixin ( @Header, @Decorator )
{
    routine Test(){
        io.writeln( 'MyMixin::Test()' )
    }
    routine PrefixTest(){
        io.writeln( 'MyMixin::PrefixTest()' )
    }
    routine TestSuffix(){
        io.writeln( 'MyMixin::TestSuffix()' )
    }
    routine PrefixTestSuffix(){
        io.writeln( 'MyMixin::PrefixTestSuffix()' )
    }
}

obj = MyMixin()
obj.Test()
obj.PrefixTest()
obj.TestSuffix()
obj.PrefixTestSuffix()
@[code]

@[text]






@[name]
dao.class.aspect
@[name]

@[title]
Aspect Class
@[title]


@[text]


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.


To avoid unintentional application of aspects, a class can only be modified
by aspects that are accessible at the definition point of the class.
Furthermore, only aspects defined in the same file as the class
or in the directly loaded file will be automatically applied.


@[code]
class @AspectForAnyClass for ~  # To be applied to any classes;
{
    var injected = {}

	# This is not a decorator!
    routine @AspectForAnyClass(){
        io.writeln( 'In @AspectForAnyClass():' );
        injected = { 1, 2, 3 }
    }

    # This decorator will also be applied to the default constructors:
    routine @DecoratorForAnyMethod( meth(args) : routine ) for ~ {
        io.writeln( 'In @DecoratorForAnyMethod():', std.about(meth) )
        io.writeln( injected )
        return meth( args, ... )
    }
}

# For classes with names prefixed with My:
class @AspectForMyClasses for My~
{
    routine @Method( meth(args) : routine ) for Method~ {
        io.writeln( 'In @AspectForMyClasses::@Method():', std.about(meth) )
        return meth( args, ... )
    }
}

class MyClass
{
    routine Method(){ io.writeln( 'MyClass::Method()' ) }
}

k = MyClass()  # Invoke the default constructor of Klass;
k.Method()
@[code]

@[text]






@[name]
dao.interface
@[name]

@[title]
Abstract Interface
@[title]


@[text]
Abstract interface is a type that describes how an object can be used,
by specifying what methods and overloaded operators the object can support.
An object is compatible (matching) to an interface type,
if only if the object supports all the methods and operators that are
specified by the interface.
Interface is an abstract type, since no instance can be created from an interface,
also all the methods of an interface are abstract without implementation.


Here is a simple interface that contains a size checking method,
@[code]
interface HasSize
{
	routine size()=>int
}
@[code]
Now we can define a function that can take a parameter of any object that is
compatible to this interface,
@[code]
routine PrintSize( object: HasSize )
{
	io.writeln( object.size() )
}
@[code]
Then this function can be called upon types such as @[green]string@[green],
@[green]list@[green] or @[green]map@[green] etc.
@[code]
PrintSize( 'hello world' )
PrintSize( { 1, 2, 3 } );
@[code]


Interface supports inheritance in the same way as class does,
@[code]
interface Resizable : HasSize
{
	routine resize( size :int )
}
@[code]
Similarly,
@[code]
routine Resize( object: Resizable, size: int )
{
	io.writeln( 'old size:', object.size() )
	io.writeln( 'new size:', size )
	object.resize( size )
}

ls = {}
Resize( ls, 5 )
io.writeln( ls )
@[code]


Interface also supports operator overloading, however, built-in operators
for built-in types cannot be checked against an interface, because they
are not implemented as methods. So interfaces are normally more useful
with class instances and wrapped C/C++ types.


Interfaces with the same set of abstract methods are interchangeable,
@[code]
interface HasSize2
{
	routine size()=>int
}
routine PrintSize2( object: HasSize2 )
{
	o :HasSize = object; # assign an object of "HasSize2" to a variable of "HasSize";
	io.writeln( object.size() )
}
PrintSize2( {} );
@[code]


Just for testing,
@[code(test)]
interface HasSize
{
	routine size()=>int
}
routine PrintSize( object: HasSize )
{
	io.writeln( object.size() )
}
PrintSize( 'hello world' )
PrintSize( { 1, 2, 3 } );

interface Resizable : HasSize
{
	routine resize( size :int )
}
routine Resize( object: Resizable, size: int )
{
	io.writeln( 'old size:', object.size() )
	io.writeln( 'new size:', size )
	object.resize( size )
}

ls = {}
Resize( ls, 5 )
io.writeln( ls )



interface HasSize2
{
	routine size()=>int
}
routine PrintSize2( object: HasSize2 )
{
	o :HasSize = object;
	io.writeln( object.size() )
}
PrintSize2( {} );
@[code(test)]



@[text]



