From: sparre@meyer.fys.ku.dk (Jacob Sparre Andersen)
Subject: Re: How to Use Abstract Data Types
Date: 1998/04/23
Date: 1998-04-23T00:00:00+00:00 [thread overview]
Message-ID: <6hnea1$6qv$1@balder.adm.ku.dk> (raw)
In-Reply-To: 6hm556$95u$1@nnrp1.dejanews.com
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 10657 bytes --]
------------------------------------------------------------------------------
-- Jacob:
--
-- This message should be ready to compile.
--
-- My reply is directed only to the problem Adam presented. There are no
-- general guidelines here (that I am aware of).
--
-- I know that my choice of coding style can be (and has been) discussed,
-- but lets keep it separate from the library/OO ADT business.
------------------------------------------------------------------------------
-- Adam (adam@irvine.com):
--
-- 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.
------------------------------------------------------------------------------
-- Jacob:
--
-- Here is how I see the problem at hand:
--
-- You have books of various kinds. The common features of all kinds
-- of all kinds of books are collected in type Abstract_Book.Object.
--
-- A library is a collection of books. You can walk through a library
-- looking for a book, add books to a library, remove books from a library
-- (even though you shouldn't), read books in a library, and you can
-- borrow books from and return them to a library.
--
-- Some libraries even have indexes to the library so you can look up
-- books by their title, author, or subject.
------------------------------------------------------------------------------
-- Abstract book:
with Libraries;
with String_Lists;
package Abstract_Book is
type Object is abstract tagged private;
subtype Class is Object'Class;
type Reference is access all Class;
function Title (Book : in Abstract_Book.Object) return String is abstract;
function Authors (Book : in Abstract_Book.Object) return String_Lists.List
is abstract;
function Subject (Book : in Abstract_Book.Object)
return Libraries.Subject_Code is abstract;
private
-- I have chosen to keep the base information about the books out of
-- Abstract_Book.Object in case we are going to work with "books" where
-- the information can be found through some other means.
type Object is abstract tagged null record;
end Abstract_Book;
------------------------------------------------------------------------------
-- Abstract library:
with Abstract_Book;
with Libraries;
package Abstract_Library is
type Object is abstract tagged private;
subtype Class is Object'Class;
type Reference is access all Class;
Full : exception;
Not_Found : exception;
procedure Add (To : in out Abstract_Library.Object;
Book : in Abstract_Book.Class;
ID : out Libraries.Book_ID) is abstract;
procedure Remove (From : in out Abstract_Library.Object;
ID : in Libraries.Book_ID;
Book : out Abstract_Book.Class) is abstract;
procedure Remove (From : in out Abstract_Library.Object;
Book : in Libraries.Book_ID) is abstract;
procedure Read_Book (Library : in Abstract_Library.Object;
ID : in Libraries.Book_ID;
Book : out Abstract_Book.Class) is abstract;
procedure Borrow (From : in out Abstract_Library.Object;
ID : in Libraries.Book_ID;
Book : out Abstract_Book.Class) is abstract;
procedure Return_Book (Library : in out Abstract_Library.Object;
Book : in Abstract_Book.Class) is abstract;
type Look_At_Reference is
access procedure (Book : in Abstract_Book.Class;
ID : in Libraries.Book_ID;
Stop : out Boolean);
procedure Walk_Through (Library : in Abstract_Library.Object;
Look_At : in Look_At_Reference;
Terminated : out Boolean);
type Process_Reference is
access procedure (Book : in out Abstract_Book.Class;
Stop : out Boolean);
procedure Walk_Through (Library : in Abstract_Library.Object;
Process : in Process_Reference;
Terminated : out Boolean);
private
type Object is abstract tagged null record;
end Abstract_Library;
------------------------------------------------------------------------------
-- Abstract book query:
with Libraries;
package Abstract_Book_Query is
type Object is abstract tagged private;
subtype Class is Object'Class;
type Reference is access all Class;
-- The initial state of a query should always be before the first result
-- from the query.
--
-- Current will fail if called before Next has been called.
procedure Current (Query : in Abstract_Book_Query.Object;
Book : out Libraries.Book_ID) is abstract;
procedure Next (Query : in out Abstract_Book_Query.Object;
Book : out Libraries.Book_ID) is abstract;
function End_Of_Query (Query : in Abstract_Book_Query.Object)
return Boolean is abstract;
private
type Object is abstract tagged null record;
end Abstract_Book_Query;
------------------------------------------------------------------------------
-- Abstract indexed library:
with Abstract_Book_Query;
with Abstract_Library;
with Libraries;
with Pattern_Matching;
package Abstract_Indexed_Library is
type Object is abstract new Abstract_Library.Object with private;
subtype Class is Object'Class;
type Reference is access all Class;
-- Here I declare *abstract* constructors for some book queries.
-- You will have to declare a non-abstract descendant of
-- Abstract_Book_Query.Object to implement the constructors.
function Search_For_Title (Library : in Abstract_Indexed_Library.Object;
Pattern : in Pattern_Matching.Pattern)
return Abstract_Book_Query.Class is abstract;
function Search_For_Author (Library : in Abstract_Indexed_Library.Object;
Pattern : in Pattern_Matching.Pattern)
return Abstract_Book_Query.Class is abstract;
function Search_For_Subject (Library : in Abstract_Indexed_Library.Object;
Subject : in Libraries.Subject_Code)
return Abstract_Book_Query.Class is abstract;
private
type Object is abstract new Abstract_Library.Object with null record;
end Abstract_Indexed_Library;
------------------------------------------------------------------------------
-- Adam:
--
-- One of the functions I would want is one to search for all books whose
-- title matches a certain regular expression.
--
-- [cut]
--
-- 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.
------------------------------------------------------------------------------
-- Jacob:
--
-- I rewrite your procedure List_Books_With_Matching_Titles with some minor
-- changes:
with Abstract_Book_Query;
with Abstract_Indexed_Library;
with Libraries;
with Pattern_Matching;
procedure List_Books (Library : in Abstract_Indexed_Library.Class;
Title : in Pattern_Matching.Pattern) is
use Abstract_Book_Query;
use Abstract_Indexed_Library;
Query : Abstract_Book_Query.Reference;
Book : Libraries.Book_ID;
begin
Query := new Abstract_Book_Query.Class' (Search_For_Title
(Library => Library,
Pattern => Title));
while not End_Of_Query (Query.all) loop
Next (Query => Query.all,
Book => Book);
--List_Book (Book);
end loop;
end List_Books;
------------------------------------------------------------------------------
-- Various stuff to get things to compile:
package Libraries is
type Subject_Code is new String (1 .. 6);
subtype Book_ID is Natural;
end Libraries;
package Pattern_Matching is
type Pattern is new String;
end Pattern_Matching;
package String_Lists is
type List is new String;
end String_Lists;
-- Greetings,
--
-- Jacob
--
----------------------------------------------------------------------------
-- Jacob Sparre Andersen -- E-mail: Jacob.Sparre.Andersen@risoe.dk --
-- National Laboratory Ris� -- Phone.: (+45) 46 77 51 23 --
-- Systems Analysis -- Fax...: (+45) 46 77 51 99 --
----------------------------------------------------------------------------
next prev parent reply other threads:[~1998-04-23 0:00 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
1998-04-22 0:00 How to Use Abstract Data Types adam
1998-04-23 0:00 ` Jacob Sparre Andersen [this message]
1998-04-30 0:00 ` Robert I. Eachus
[not found] ` <matthew_heaney-ya023680003004981709380001@news.ni.net>
1998-05-05 0:00 ` Stephen Leake
1998-05-05 0:00 ` Matthew Heaney
1998-05-06 0:00 ` Stephen Leake
-- strict thread matches above, loose matches on Subject: below --
1998-04-30 0:00 adam
1998-05-06 0:00 ` Robert I. Eachus
1998-05-04 0:00 adam
1998-05-06 0:00 ` Robert I. Eachus
replies disabled
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox