2.4. Modular inheritance

It is possible to inherit all the symbols of a module with the inherit directive. Unlike the open directive, inherited symbols become part of the public interface of a module, as well as it's private interface.

When lookup is performed, entities defined in the module are always considered before inherited ones. This is to ensure a local definition can always be used to resolve an ambiguity, and to ensure that any binding to a local definition cannot be hijacked by a non-local change in another module.

Modular inclusion is transitive because it is specified to include the whole of the public interface of one module in another, including any symbols that module inherits.

Note that as usual and unlike other programming languages, Felix inheritance is fully recursive: a module contains all the symbols it defines plus the transitive closure of all inherited modules.

In particular, it is quite possible for two modules to inherit each other, thereby ensuring they publish the same set of names: note however that local overrides may mean the definition associated with a name is different for each module.

Start C++ section to tut/examples/tut207c.flx[1 /1 ]
     1: header "#include <iostream>";
     2: header "#include <string>";
     3: 
     4: type int = "int";
     5: type string= "std::string";
     6: proc print:int = "std::cout << $1;";
     7: proc print:string= "std::cout << $1;";
     8: proc endl:1 = "std::cout << std::endl;";
     9: 
    10: module X {
    11:   fun f(a:int):int={ return 11; }
    12: }
    13: module Y {
    14:   fun g(a:int):int={ return 22; }
    15: }
    16: module Z { inherit X; inherit Y; }
    17: 
    18: // check transitivity
    19: module A {
    20:   inherit Z;
    21:   print (f 3); print " "; print (g 5); endl;
    22:   print (Z::f 3); print " "; print (Z::g 5); endl;
    23:   print (A::f 3); print " "; print (A::g 5); endl;
    24: }
    25: 
    26: 
    27: // check recurisve transitive closure
    28: module P { inherit Q; fun ff(a:int):int={return 33;}}
    29: module Q { inherit P; fun gg(a:int):int={return 44;}}
    30: module R {
    31:   inherit P;
    32:   print (ff 1); print " "; print (gg 1); endl;
    33:   print (P::ff 1); print " "; print (P::gg 1); endl;
    34:   print (Q::ff 1); print " "; print (Q::gg 1); endl;
    35:   print (R::ff 1); print " "; print (R::gg 1); endl;
    36: }
    37: 
    38: module W {
    39:   module J { val a:int = 1;}
    40:   inherit J;
    41:   print a; endl;
    42: }
    43: print W::a; endl;
    44: 
End C++ section to tut/examples/tut207c.flx[1]