Reputation: 6368
In the following code:
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Containers; use Ada.Containers;
with Ada.Containers.Vectors;
procedure Main is
package IEnumerators is
-- An umbrella class for all things that are iterable
type IEnumerator is interface;
procedure Move_Next (Self : in out IEnumerator) is abstract;
end IEnumerators;
use IEnumerators;
package IEnumerables is
-- The iterator for IEnumerator
type IEnumerable is interface;
function Get_Enumerator
(Self : IEnumerable) return IEnumerator is abstract;
end IEnumerables;
use IEnumerables;
package Lists is
-- An IEnumerable whose underlying is a vector
package Integer_Vector is new Ada.Containers.Vectors
(Element_Type => Integer, Index_Type => Positive, "=" => "=");
-- FAIL: type must be declared abstract or "Get_Enumerator" overridden
-- Fair enough, there's a problem with Get_Enumerator in the body
type List is new IEnumerable with record
Members : Integer_Vector.Vector;
end record;
end Lists;
package body Lists is
type List_Enumerator is new IEnumerator with null record;
overriding procedure Move_Next (Self : in out List_Enumerator) is
begin
null; -- do something
end Move_Next;
overriding
-- FAIL: subprogram "Get_Enumerator" is not overriding.
function Get_Enumerator (Self : List) return List_Enumerator
is
Result : List_Enumerator;
begin
return Result;
end Get_Enumerator;
end Lists;
begin
null;
end Main;
I don't understand why the overriding Get-Enumerator fails; it has the same signature as the one in the package IEnumerables (List is a concrete IEnumerable and List_Enumerator is a concrete IEnumerator).
Where have I gone wrong?
Upvotes: 1
Views: 652
Reputation: 6430
First, the compiler complains about the spec, because you don't override Get_Enumerator
package Lists is -- An IEnumerable whose underlying is a vector
package Integer_Vector is new Ada.Containers.Vectors
(Element_Type => Integer, Index_Type => Positive, "=" => "=");
type List is new IEnumerable with record
Members : Integer_Vector.Vector;
end record;
overriding
function Get_Enumerator
(Self : List) return IEnumerator;
Second, the compiler complains in the body, because the overriding must be in the spec (where the type declaration is), and you also have the wrong signature. Ada does not support co-derivation:
-- same signature as the parent
-- overriding is usually not indicated in both spec and body
function Get_Enumerator (Self : List) return IEnumerator
is
Result : List_Enumerator;
begin
return Result; -- now this won't compile, wrong type
end Get_Enumerator;
Third, you're not returning the correct type according to the inherited signature, like I said above, Ada does not support co-derivation. You can, however, tell the compiler you want to return IEnumerator, or any type derived from IEnumerator, like so:
package IEnumerables is
-- The iterator for IEnumerator
type IEnumerable is interface;
function Get_Enumerator
(Self : IEnumerable) return IEnumerator'Class is abstract;
end IEnumerables;
and the overriding in Lists
spec:
overriding
function Get_Enumerator
(Self : List) return IEnumerator'Class
and Lists
body:
function Get_Enumerator (Self : List) return IEnumerator'Class
is
Result : List_Enumerator;
begin
return Result;
end Get_Enumerator;
Upvotes: 4