Augments and Aspects
Augments
Augments are a way to add additional members and base types to a class separate from its primary definition - in other words, augments allow you to make distributed partial class definitions.
- When you define an augment it is as if you had typed all that code into the original class definition.
- Augments can only add new member definitions - they cannot redefine existing members (see aspects if you want to do that).
- Augments can be defined before or after the main class. They are applied in the order in which they are defined, with all the augments from the original file first, then all the augments from the first included file, and so on.
- Augments are a useful way to implement basic separation of concerns - for example, they allow drawing logic to be defined independently of behavior logic, which in turn allows the drawing code to be cleanly swapped out.
- See also: overlaying augments, below.
Examples:
class Hero
method update:
decide_what_to_do()
endClass
...
augment Hero
method draw:
draw_this_hero()
endAugment
# A Hero object now has two methods: update() and draw().
class Test
method init:
println( 6342.num_digits ) # prints: 4
endClass
# Add a new method to class Global
augment Global
method num_digits( Int32 num, Int32 base=10 ).Int32:
local Int32 count = 1
num /= 10
while (num?) ++count; num /= 10
return count
endAugment
Aspects
Slag aspects are a unique approach to aspect-oriented programming and a powerful expansion of the idea of Java interfaces.
In simplest terms, an aspect is like a Java interface that can include method bodies and additional instance variables in its definition. Where Java implements interfaces, Slag incorporates aspects. During aspect incorporation, aspect method bodies are "cut & pasted" into existing methods of the same name. The syntax for controlling the order of this aspect layering is similar to that of making a prior (super-class) call.
Example:
class Test : IncreaseFormatValue, AddFormatBrackets
METHODS
method init:
println( format(5) ) #prints out: <6>
method format( Int32 n ).String:
return "$" (n)
endClass
overlaying aspect IncreaseFormatValue
METHODS
method format( Int32 n ).String:
return underlying( n + 1 )
endAspect
overlaying aspect AddFormatBrackets
METHODS
method format( Int32 n ).String:
return "<$>" (underlying(n))
endAspect
Note that after the above example is compiled, there is a single format() method that is called once.
- Each aspect should be declared as overlaying or underlying as a whole, which indicates the default order methods should be merged in. Individual methods can then be specified as being underlying or overlaying contrary to the default.
- In the class declaration "class ExtendedClass : BaseClass, AspectAlpha, AspectBeta", methods are layered in the following order (the top one listed here is the bottom-most layer):
- All methods from BaseClass.
- Underlying methods from AspectAlpha.
- Underlying methods from AspectBeta.
- All methods from ExtendedClass.
- Overlaying methods from AspectAlpha.
- Overlaying methods from AspectBeta.
(Note that all "underlying" code references from underlying AspectAlpha methods would be adjusted to be "prior" calls instead)
- Methods may reference "underlying" code even if there is no underlying code as long as no attempt is made to use an underlying return value. Such calls to non-existent code are silently removed.
- Aspects can be used just like Java interfaces (where all methods are abstract) if desired.
- Object references can be of aspect types rather than class types. The same method-calling rules and restrictions apply as are found with Java interfaces.
Overlaying Augments
Augments are totally separate from a class but cannot redefine existing member definitions. Aspects can redefine functionality at will but they must be specified as a base type for a class. An overlaying augment is a way to combine the power of both.
- An overlaying augment allows you to add and redefine behavior as an entirely independent definition.
Example:
# Modify class String to print a stack trace whenever substring() is called.
overlaying augment String
method substring( Int32 i1, Int32 i2 ).String:
println( "substring($,$)" (i1,i2) )
return underlying(i1,i2)
endAugment
# The above code is shorthand for:
overlaying aspect AnonAspect2352
method substring...
endAspect
augment String : AnonAspect2352;
- Login to post comments
