initialize
vs initialise
Result: get overriding when don't want it, or don't get it when it's wanted
Solution: Mark routines that override
type Shape is tagged record x, y: integer; end record;
function area(S: Shape) return Natural is abstract;
type Circle is new Shape with radius; end record;
overriding -- this function MUST override one in parent
function area(C: Circle) return Natural;
function new_function(C: Circle) return Natural;
-- Does new_function override?
Most useful when compiler switch requires overriding
keyword
Ada allows programmer to control whether dynamic dispatch occurs
-- formal parameter s is classwide. Calls using s will be dynamic
procedure print(s: Shape'Class) is
begin
put(area(s)); -- Dynamic
put(area(Shape(s))); -- NOT Dynamic
-- Object prefix notation
put(s.area); -- Dynamic
put(Shape(s).area); -- NOT Dynamic
In Java we get dynamic dispatch with this code:
Object[] a = new Object[N]; a.fillitwithvariousobjects();
In Ada we can have arrays of objects, but avoid dynamic dispatch
procedure Dyn_Dispatch is
type Any_Shape_Ptr is access Shape'Class
AA: array (1 .. MaxShapes) of Any_Shape_Ptr;
begin
-- Fill array ...
for i in AA'range loop
print(AA(i).area);
-- Dynamic Dispatch because AA is a classwide type
end loop;
end Dyn_Dispatch;
procedure No_Dyn_Dispatch is
CA: array (1 .. MaxCircles) of Circle;
SA: array (1 .. MaxSquares) of Square;
begin
-- Fill arrays ...
for i in CA'range loop
print(area.CA(i)); -- not dynamic: CA not classwide
end loop;
for i in SA'range loop
print(area.SA(i)); -- not dynamic
end loop;
end No_Dyn_Dispatch;
Use an array of pointers to have an array of any size shape
The pointers can point to shapes stored on the other arrays
procedure No_Heap_Alloc is
type Any_Shape_Ptr is access all Shape'Class
AA: array (1 .. MaxShapes) of Any_Shape_Ptr;
CA: array (1 .. MaxCircles) of aliased Circle;
SA: array (1 .. MaxSquares) of aliased Square;
begin
-- Fill circle and square arrays ...
for i in AA'range loop
if choose_circle(i) then
AA(i) := CA(next_circle(i))'access;
else
AA(i) := SA(next_square(i))'access;
end if;
end loop;
end No_Dyn_Dispatch;
Consider this Java code:
Class A{int key;}
Class B extends A{} // What happens if we add a key here?
Class C extends B{void useKey(){S.o.p(key);}
Why does Java allow this?
key
to A when it already exists in BOnly assign entire records
t: Transaction := (check, 100, 100);
begin
t.kind := cash; -- compile error
Check discriminant at runtime
t: Transaction := (check, 100, 100);
begin
if t.exp_date -- run time error
Declare pointer variables to not allow null values
procedure p(n: not null node_ptr);
...
-- client
q := null;
p(q); -- error
Error caught at point of call
all
type intPtr is access all Integer
aliased
I: aliased Integer