Using the passed-by-reference nature of arrays, it is possible to use an array to represent a data structure (similar to a C struct passed by pointer) that is passed to functions that manipulate it:
example program ch6_ex1 |
---|
{ calculate the overall intensity of the color } function color_update(CLR); begin CLR['intensity'] := (CLR['red']/255 + CLR['green']/255 + CLR['blue']/255)/3; end; function main(ARGV); begin CLR1['red'] := 15; CLR1['green'] := 200; CLR1['blue'] := 60; color_update(CLR1); fawk_print(CLR1['intensity']); end; |
This helps implementing data driven programming:
To ease using the above pattern, fawk implements the "." operator that is a shorthand syntax for an array indexing with the string version of the field name. The following two array references are equivalent:
arrname.fieldname arrname['fieldname']
Using this syntax the above example cn be rewritten into a more readable form:
example program ch6_ex2 |
---|
{ calculate the overall intensity of the color } function color_update(CLR); begin CLR['intensity'] := (CLR.red/255 + CLR.green/255 + CLR.blue/255)/3; end; function main(ARGV); begin CLR1.red := 15; CLR1.green := 200; CLR1.blue := 60; color_update(CLR1); fawk_print(CLR1.intensity); end; |
The next logical step is to bundle the functions that can manipulate the data, to the same array. This is possible since function references can be saved in variables or in array members (see section 4.6.):
example program ch6_ex3 |
---|
{ load a color array with component values } function color_load(CLR; r; g; b); begin CLR.red := r; CLR.green := g; CLR.blue := b; end; { calculate the overall intensity of the color } function color_update(CLR); begin CLR['intensity'] := (CLR.red/255 + CLR.green/255 + CLR.blue/255)/3; end; function main(ARGV); begin { initialize the object } CLR1.update := color_update; CLR1.load := color_load; { load and update } CLR1.load(CLR1, 15, 200, 60); CLR1.update(CLR1); fawk_print(CLR1.intensity); end; |
It is possible to set up a "base class" for the color structure so that different object instances can be created more easily:
example program ch6_ex4 |
---|
{ load a color array with component values } function color_load(CLR; r; g; b); begin CLR.red := r; CLR.green := g; CLR.blue := b; end; { calculate the overall intensity of the color } function color_update(CLR); begin CLR['intensity'] := (CLR.red/255 + CLR.green/255 + CLR.blue/255)/3; end; function main(ARGV); begin { initialize the "base class" } COLOR.update := color_update; COLOR.load := color_load; { create an instance of COLOR called CLR1 } for i in COLOR do CLR1[i] := COLOR[i]; { load and update } CLR1.load(CLR1, 15, 200, 60); CLR1.update(CLR1); fawk_print(CLR1.intensity); end; |
Obviously "multiple inheritance" can be implemented the same way, simply using two loops for copying fields from two different "base classes":
example program ch6_ex5 |
---|
{ load a color array with component values } function color_load(CLR; r; g; b); begin CLR.red := r; CLR.green := g; CLR.blue := b; end; { calculate the overall intensity of the color } function color_update(CLR); begin CLR['intensity'] := (CLR.red/255 + CLR.green/255 + CLR.blue/255)/3; end; { convert a single digit to hex } function hexdigit(digit); begin hexdigit := '?'; if digit < 10 then hexdigit := digit; if digit = 10 then hexdigit := 'A'; if digit = 11 then hexdigit := 'B'; if digit = 12 then hexdigit := 'C'; if digit = 13 then hexdigit := 'D'; if digit = 14 then hexdigit := 'E'; if digit = 15 then hexdigit := 'F'; end; { convert a byte value to a 2-digit hex string } function tohex2(val ;d1;d2); begin d1 := int(val / 16); d2 := val % 16; tohex2 := hexdigit(d1) @ hexdigit(d2); end; { convert the color to html color code } function html_print_color(CLR); begin html_print_color := '#' @ tohex2(CLR.red) @ tohex2(CLR.green) @ tohex2(CLR.blue); end; function main(ARGV); begin { initialize the color "base class" } COLOR.update := color_update; COLOR.load := color_load; { initialize the html "base class" } HTML.print_color := html_print_color; { create an instance of COLOR+HMTL called CLR1 } for i in COLOR do CLR1[i] := COLOR[i]; for i in HTML do CLR1[i] := HTML[i]; { load and update } CLR1.load(CLR1, 15, 200, 60); fawk_print(CLR1.print_color(CLR1)); end; |
There are many major features of OOP missing: there are no automatisms, everything needs to be done by the user, in code. Most notably there is no constructor or destructor and passing the object as the first argument is done manually, there is no "this" in functions.