Reputation: 385
I am trying to model a set of Parsers in Ada based on interface below:
package Parsers is
type Parser is interface;
type DataArray is array(Integer range <>) of String(1..100);
function Parse(Object : access Parser; FilePath : String) return DataArray is abstract;
end Parsers;
The first Parser interface member is a text parser show below:
with Parsers;
package TextParsers is
type Parser is new Parsers.Parser with null record;
overriding function Parse(Object : access Parser; FilePath : String) return Parsers.DataArray;
end TextParsers;
with Parsers;
use Parsers;
package body TextParsers is
overriding function Parse(Object : access Parser; FilePath : String) return Parsers.DataArray is
Data : Parsers.DataArray (0..144);
begin
-- just stubbed out
return Data;
end Parse;
end TextParsers;
And finally, I would like to have a factory method create these Parsers based on the path provided, like detecting if it was a txt file or maybe a csv, etc. Here is the factory code:
with Parsers;
use Parsers;
package ParserFactories is
function GetParser(Path : String) return Parsers.Parser;
end ParserFactories;
with Parsers, TextParsers;
package body ParserFactories is
function GetParser(Path : String) return Parsers.Parser is
Text : TextParsers.Parser;
Parse : Parsers.Parser'Class := Text;
begin
return Parse;
end GetParser;
end ParserFactories;
I keep getting a "dynamically tagged expression not allowed" compilier error, and I cannot figure out how I can create these objects that implement the Parser interface and return it out of this function. Is there a way to do this in Ada?
Upvotes: 1
Views: 1031
Reputation: 4198
The answer is that you don't return the interface's type, but the type that the object is... or else you can return the interface'class to indicate that you're going to assign it to that abstract-typed variable.
Procedure Testing is
package Interface_Test is
Type IBob is interface;
Function Make Return IBob is abstract;
Function Image( Object : In IBob ) Return String is abstract;
Generic
Type Data is (<>);
Default_Data : In Data;
Package Container is
Type Data_Container is NEW IBob with private;
private
Type Data_Container is new IBob with record
Info : Data:= Default_Data;
end record;
Overriding Function Make Return Data_Container;
Overriding Function Image(Object : In Data_Container) Return String;
end Container;
end Interface_Test;
package Body Interface_Test is
Package Body Container is
Function Make Return Data_Container is
begin
Return Result : Data_Container;
end Make;
Function Image( Object : Data_Container ) Return String is
begin
return Data'Image( Object.Info );
end image;
end Container;
end Interface_Test;
package J is new Interface_Test.Container( Integer, 1 );
use type J.Data_Container;
Test : J.Data_Container:= J.Make;
Use Ada.Text_IO;
Begin
put_line( Test.Image );
End;
Upvotes: 1
Reputation: 1804
You are trying to return a Parsers.Parser
type. This is not allowed (and not what you intend to do). Change it to Parsers.Parser'Class
instead.
Upvotes: 2