From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,6b85f5fd782a1527,start X-Google-Attributes: gid103376,public From: adam@irvine.com Subject: How to Use Abstract Data Types Date: 1998/04/22 Message-ID: <6hm556$95u$1@nnrp1.dejanews.com> X-Deja-AN: 346819300 X-Http-User-Agent: Mozilla/3.0 (X11; I; Linux 2.0.18 i586) Organization: Deja News - The Leader in Internet Discussion X-Article-Creation-Date: Thu Apr 23 01:22:46 1998 GMT Newsgroups: comp.lang.ada Date: 1998-04-22T00:00:00+00:00 List-Id: I'm just starting to use some of the advanced OO features of Ada 95, and I've run into a situation that I don't know what the best solution is. Or maybe I'm completely confused about something. Here's an example of what I'm trying to accomplish. I'd like to define an abstract data type, Library, that denotes a collection of books. Since this collection could be implemented in several ways---say, as a flat file, or a file organized as a tree, or perhaps not a file at all but rather by querying some other site on the Internet---the type would be an abstract tagged type, and the package that declares it would declare abstract procedures to deal with it. I'd assume that the type Book, which represents one book, would be an abstract type, also. One of the functions I would want is one to search for all books whose title matches a certain regular expression. My usual idiom for this sort of scan is to declare four subprograms---something like Start_Scan (which gets things started but doesn't return any items), More_Items (which returns TRUE if there are more items to return), Next_Item (which returns the next one), and Close_Scan (to clean up). This idiom also involves declaring a type to hold "current item" information needed by the scan routines; an object of this type is set up by Start_Scan, More_Items tests the object, and Next_Item modifies it. I strongly prefer this over having the current scan information "hidden" globally inside the package body, since it means there's no problem for two parts of the calling program to conduct two scans in parallel. If I define a record to hold the current scan information, it would also have to be abstract (right?), since its contents would vary depending on the implementation. That is, for libraries implemented as a tree file, it might contain a stack of node addresses, or something like that. So say my package spec looks like this: package Library_Package is type Library is abstract tagged null record; type Book is abstract tagged null record; type Scan_Info is abstract tagged null record; ... procedure(s) to set up a new Library object procedure Scan_By_Title (Lib : in Library; Reg_Expression : in String; Scan : out Scan_Info; RE_Error : out Boolean); function More_Books (Scan : Scan_Info) return Boolean; procedure Next_Book (Scan : in out Scan_Info; Bk : out Book); procedure Close_Scan (Scan : in out Scan_Info); ... etc. end Library_Package; For Scan_By_Title, RE_Error would be set to TRUE if Reg_Expression is ill-formed. But it looks like this isn't going to work. If I were to write a procedure that lists all the books in a library whose titles match, I'd want to be able to write: procedure List_Books_With_Matching_Titles (Lib : in Library'Class; Title_Pattern : in String) is ... declarations begin Scan_By_Title (Lib, Title_Pattern, List_Scan, Error); if Error then Insult_The_User; return; end if; while More_Books (List_Scan) loop Next_Book (List_Scan, The_Book_To_List); List_Book (The_Book_To_List); end loop; Close_Scan (List_Scan); end List_Books_With_Matching_Titles; But I don't see how this can be done, since I can't declare List_Scan. I can't declare it as Library_Package.Scan_Info since that is an abstract type, and I can't declare it as Library_Package.Scan_Info'Class since I need an initializer. I guess I could declare it as Scan_Info'Class if I turned Scan_By_Title into a function, but then I'd have to find some other way to take care of the RE_Error output (in this particular case, I could use an exception, but imagine a case where I want to return something that isn't a simple success/failure boolean). I also don't see how to declare The_Book_To_List, and I can't see turning Next_Book into a function since Scan has to be an "in out" parameter. Am I missing something trivial here? What is the cleanest way to accomplish what I'm trying to do? This looks like such a typical use of polymorphism that I'd be surprised if there were no intuitive way to do it. -- thanks, Adam -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/ Now offering spam-free web-based newsreading