Chapter: Inheritance

by Andrzej Salwicki


What it is, the inheritance?

Inheritance is an operation on modules of a program.There are two operations on modules: nesting and inheritance. We know the nesting of modules: one module may be put inside another module.(It does not apply to C, C++ and many other languages!). Nesting enables the nested module to access all the resources declared in the embracing module. If there two or more modules M1, M2, ... nested in a module M then all of them share the resorces of the module M and all resources declared in a module Mi {i=1, 2, ... } are its private property which is not accessible from the outside of the module Mi.

Inheritance is a complementary way of composition of modules. When nesting assures sharing, the inheritance is to assure that an object (or activation record of ...) will be equipped with its private copy of the resources defined in an inherited module. Two are needed to dance the waltz. Similarly, two modules are needed for the inheritance operation on modules: one module, say A,, which is inherited. And another module, say B, which inherits. One can say also that module B is an extension of the module A

Subtypes. This notion of inheritance permits to talk of subtypes of a type.

Concatenation rule, act 1

Example Let us consider the notion of a bill and its various extensions. Any bill contains information on the sum to be paid, the date, the remark whether the sum has been paid or not and the additional operations specific for the particular transaction and the company issuing the bill.
Let us consider the bills for electricity and gas, bills for electricity only (if your house is not connected to a gas network) and thelephone bills. We remark immediately that there are common parts of different bills. We can make a declaration of class bill as follow

	unit bill: class(who: person, day: date);
	     var amount: integer, paid: Boolean; 
	end bill;
and now we can prepare bills for electricity
	unit electricity_bill: bill class(kWh: integer);
	begin
	   amount := kWh * price_kWh     (* let us remark that price_kWh is external to the module *)
        end electricity_bill;
which will have the following structure
level bill
who: person a value
day: date a value
amount: integer a value
paid: Boolean false
level electricity
kWh: integer a value
this generalises to the following rule:
Let us suppose that two classes A
unit A: class(pfA);
    <declarations A>
begin
    <instructionsA>
end A 
and B were declared:
unit B: class(pfB);
     <declarationsB>
begin
     <instructionsB>
end B
if you prefix the word class in the declaration of B by the name A
unit B: A class(pfB);
     declarationsB
begin
     instructionsB
end B
then any object of this class B is created as if the class B had the scheme given on the right -->
unit B: class(pfA, pfB);
     declarationsA;
     declarationsB
begin
     instructionsA;
     instructionsB
end B
The class B is said to be a subclass of class A. This notion is defined by induction: If C is a subclass of class B and B is a subclass of class A then C is subclass of class A. Thus we can create the hierarchies of types organized in trees. Who am I? object relations is and in Axiom of type consistency Let x be a variable of type T. In any moment of the execution of program the value of the variable x is an object of class T or of a subclass of class T.

What I am offering, act 1?

An object is offering its resources. Which ones?

Concatenation rule act 2 (Prologue &Epilogue)

Example 1 (ctd.) What will happen if one adds the statements that print a bill in the class bill and in its extensions? unit bill: class(who: person, day: date); var amount: integer, paid: Boolean; begin writeln(“ Bill issued: ”, day); writeln(“ for Mrs/Mr. ”, who); inner; (* this dummy statement separates the prologue from the epilogue of the class bill. We can conceive it as slot for the instructions of inherinting units *) writlen(“ the amont to be paid  is ”, amount) end bill; and now we can prepare bills for electricity unit electricity_bill: bill class(kWh: integer); begin amount := kWh * price_kWh; writeln(“ you have used ”,kWh,   ”kWh at price: ”, price_kWh); end electricity_bill; Since inner pseudocommand appearing in the class bill is replaced by the commands of the class electricity_bill we assure the desired look of the bill where the amount of the sum to be paid is calculated first and printed later. unit A: class(pfA); begin ; inner; (* this is a slot to put instructions*) end A unit B: class(pfB); begin end B  if you prefix the word class in the declaration of B like unit B: A class(pfB); begin end B then any object of this class B is created in accordance with the scheme given on the right  unit B: class(pfA, pfB); ; begin ; ; end B   You can conceive inner as a slot where the instructions of the inheriting unit will be placed. In fact you can put the pseudoinstruction inner in any place in the code of the class A. It is not necessarily that inner separates the instructions of class A into to disjoint sequences. The only condition imposed on you is that inner may appear at most oce in a class. It is assumed that inner appears par default at the end of a class, just before end.

Concatenation rule act 3 (Visibility & Static binding of identifiers)

Q.I have heard of possible conflicts in inheriting modules. What does it mean? Be easy. No conflicts in Loglan. Let us look first at an example. unit A: class; var x: T1, z: T3 begin I(x,z); inner; J(x) end A; unit B: A class; var x: T2, y: T4 begin K(x,z,y) end B  in the presence of the above declarations the following command o := new B is executed as if unit B were of the form on right unit B; var xA: T1, zA: T3; var xB: T2, y: T4 begin I(x/xA, z/zA); K(x/xB, z/zA, y/yB); J(x/xA) end B   Answer: Do not worry about possible conflicts of repeating declarations of an identifier. Loglan offers a secure (no conflicts) scheme of understanding the program ... as well as the flexibility. It means, it is possible to override the default solution ... Q. What one sees then from the outside? The remote access of type o.x means o.xB but writing o qua A.x one can access the attribute xA of the level A This applies as well to other possible declarations: constants, procedures, functions, classes contained in A or B module. And inside the class B? use this A.x in order to access the x attribute of the level A

Concatenation rule act 4 (Protection mechanism)

Closing the access to an attribute. Hiding an attribute. Filtering the inherited attributes. In any class you can put a restriction specification. There are three forms of such specification. One can forbid a remote access to the variables of a class. It is done by means of close specification. It is possible to hide an attribute to any module that inherits from a current module. It is done by means of hidden specification. If you wish you may inherit only the attributes from a list. taken In any case the absence of a restriction specification means no restriction at all.

Concatenation rule act 5 (Virtual procedures and functions)

Example
unit A: class;
   unit virtual p: procedure(x,y:T);
       ...
   end p;
begin
    I(p);
    inner;
    J(p)
end A
unit B: A class;
    unit virtual p: procedure(u,v: T1);
      (* Attention type T1 must be compatible withe the  	type T *)
   end p;
begin
    K(p)
end B 
A virtual method declared in the inheriting module B will be taken as the meaning of all applicative occurrences of p in the instructions of the level A.
unit B: Aclass;
   unit virtual pB: procedure(u, v: T1)
 end pB;
begin
    I(p/pB);
    K(p/pB);
    J(p/pB)
end B
The mechanism of virtual procedures and functions offers many interesting possibilities. On the other hand it is considered as slowing the execution.

Promises

Using inheritance one can achieve various goals of programming
last update: Mon 19 Feb 1996 Andrzej Salwicki