If we subclass mbfl_default_object
to define a new class with name colour
:
mbfl_default_class_declare(COLOUR) mbfl_default_class_define _(COLOUR) _(mbfl_default_object) 'colour' red green blue
and then we instantiate colour
:
mbfl_default_object_declare(DARK_SLATE_BLUE) colour_define _(DARK_SLATE_BLUE) 72 61 139
the layout of the instance array is:
instance[0] ⇒ _(COLOUR) instance[1] ⇒ 72 instance[2] ⇒ 61 instance[3] ⇒ 139
We can subclass colour
to add a transparency field:
mbfl_default_class_declare(TRANSPARENT_COLOUR) mbfl_default_class_define _(TRANSPARENT_COLOUR) _(COLOUR) 'transparent_colour' transparency
then we can instantiate transparent_colour
:
mbfl_default_object_declare(TRANSPARENT_DARK_SLATE_BLUE) transparent_colour_define _(TRANSPARENT_DARK_SLATE_BLUE) 72 61 139 50
the layout of the instance array is:
instance[0] ⇒ _(TRANSPARENT_COLOUR) instance[1] ⇒ 72 instance[2] ⇒ 61 instance[3] ⇒ 139 instance[4] ⇒ 50
The diagram of instances and classes is as follows:
-class--------------- | mbfl_default_object | --------------------- ^ | superclass | -class- class -instance-------- | colour |<-----------------| DARK_SLATE_BLUE | ------- ----------------- ^ | superclass | -class------------- class -instance-------------------- | transparent_colour |<--------| TRANSPARENT_DARK_SLATE_BLUE | ------------------- -----------------------------
The class constructor mbfl_default_class_define()
defines functions that we can use to operate
on class instances; with the class definition:
mbfl_default_class_declare(COMPLEX) mbfl_default_class_define _(COMPLEX) _(mbfl_default_object) 'complex' real imag
the class identifier complex
is used to generate an instance constructor:
mbfl_default_object_declare(Z) complex_define _(Z) 2 3
and field accessors and mutators:
declare REAL IMAG complex_real_set _(Z) 8 complex_imag_set _(Z) 9 complex_real_var REAL _(Z) complex_imag_var IMAG _(Z) $IMAG ⇒ 8 $REAL ⇒ 9
and a class predicate:
complex_p _(Z) ⇒ true complex_p _(COLOUR) ⇒ false
Accessor and mutator functions are defined for every field in a class definition and every field of
its superclasses. So if we define colour
and its subclass transparent_colour
, we have
all the accessors and mutators for instances of transparent_colour
:
mbfl_default_class_declare(COLOUR) mbfl_default_class_declare(TRANSPARENT_COLOUR) mbfl_default_object_declare(FOREGROUND) mbfl_default_class_define _(COLOUR) _(mbfl_default_object) 'colour' red green blue mbfl_default_class_define _(TRANSPARENT_COLOUR) _(COLOUR) 'transparent_colour' transparency transparent_colour _(FOREGROUND) 11 22 33 50 declare RED GREEN BLUE TRANS transparent_colour_red_var RED _(FOREGROUND) transparent_colour_green_var GREEN _(FOREGROUND) transparent_colour_blue_var BLUE _(FOREGROUND) transparent_colour_transparency_var TRANS _(FOREGROUND) $RED ⇒ 11 $GREEN ⇒ 22 $BLUE ⇒ 33 $TRANS ⇒ 50
Notes:
_(DARK_SLATE_BLUE, red) ⇒ 72
to access the fields, which is directly usable in Bash expressions; the disadvantage is that such solution exposes a value as object’s field, which is an implementation detail.
Accessor functions allow us to change the internal representation of an object without changing its
public API. So while accessing a complex
object we can do:
declare REAL IMAG RHO THETA complex_real_var REAL _(Z) complex_imag_var IMAG _(Z) complex_rho_var RHO _(Z) complex_theta_var THETA _(Z)
and nobody knows which values are the fields and which values are computed on demand.
This document describes version 3.0.0-devel.9 of Marcos Bash Functions Library.