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,399666c22a39304c X-Google-Attributes: gid103376,public From: Richard Irvine Subject: Re: Translate this into Ada ... Date: 1996/08/22 Message-ID: <321C5BB1.3B2F@eurocontrol.fr> X-Deja-AN: 175799613 references: <3219E6E2.2F5@eurocontrol.fr> <4vfb15$ujr@watnews1.watson.ibm.com> content-type: text/plain; charset=us-ascii organization: Eurocontrol Experimental Centre, Bretigny-Sur-Orge, France mime-version: 1.0 newsgroups: comp.lang.ada x-mailer: Mozilla 2.0 (X11; I; HP-UX A.09.05 9000/755) Date: 1996-08-22T00:00:00+00:00 List-Id: Many thanks to Norman Cohen for his comprehensive reply. I certainly learnt something about Ada 95, namely that the body of the function > function New_Iterator_For > (Collection: Integer_List_Type) > return Abstract_Integer_Collections.Iterator_Type'Class; > can return a member of the class rather than something which is of type Iterator_Type'Class, i.e. > type Integer_List_Iterator_Type is > new Abstract_Integer_Collections.Iterator_Type with private; > function New_Iterator_For > (Collection: Integer_List_Type) > return Abstract_Integer_Collections.Iterator_Type'Class is > begin > return Integer_List_Iterator_Type' > (Abstract_Integer_Collections.Iterator_Type with > Next_Cell => Collection.First_Cell); > end New_Iterator_For; > In general one might like to have more than one iterator for the same collection type, each iterator implementing a different traversal policy but all having the same protocol. So for example, in the package Integer_Lists one might want to derive a second concrete type from Abstract_Integer_Collections.Iterator_Type . However, the problem arises that the function New_Iterator_For is a classwide function rooted at Abstract_Integer_Collections.Iterator_Type and as it stands will always return the first type of iterator, namely Integer_List_Iterator_Type. A possible solution is the following. Define a (generic) abstract collection which has those operations which do not mention iterators. Define a (generic) abstract iterator. Define a (generic) concrete collection which conforms to the abstract collection. Then, for each iterator type, define a (generic) package which is a child of the (generic) concrete collection. Each child package can instantiate its own abstract iterator and provide its own implementation of New_Iterator_For, which in fact returns the appropriate concrete iterator. Within each child package the implementation of the concrete collection is visible. For example, (with some naming and naming convention differences) generic type ItemType (<>) is private; package AbstractAppendableCollection_P is type AbstractAppendableCollection is abstract tagged null record; function isNotEmpty ( theCollection : AbstractAppendableCollection ) return Boolean is abstract; procedure append ( theItem : in ItemType; toTheCollection : in out AbstractAppendableCollection) is abstract; procedure removeTheLastItemFrom ( theCollection : in out AbstractAppendableCollection) is abstract; -- precondition: isNotEmpty( theCollection ); end; generic type CollectionType (<>) is private; type ItemType (<>) is private; package AbstractIterator_P is type AbstractIterator is abstract tagged null record; function aNewIteratorFor ( theCollection : CollectionType ) return AbstractIterator'Class is abstract; -- precondition: isNotEmpty( theCollection ) -- after creation the iterator points to the first item in the collection function theCurrentItem ( theIterator : AbstractIterator ) return ItemType is abstract; function atTheEnd ( theIterator : AbstractIterator ) return Boolean is abstract; procedure advance ( theIterator : in out AbstractIterator ) is abstract; -- precondition : not(atTheEnd()) procedure reset ( theIterator : in out AbstractIterator ) is abstract; -- reset the state of the iterator to be that after creation end; with AbstractAppendableCollection_P; generic type ItemType (<>) is private; package AppendableCollection_P is package ItemTypeAbstractAppendableCollection_P is new AbstractAppendableCollection_P(ItemType => ItemType); use ItemTypeAbstractAppendableCollection_P; type AppendableCollection is new AbstractAppendableCollection with private; function isNotEmpty ( theCollection : AppendableCollection ) return Boolean; procedure append ( theItem : in ItemType; toTheCollection : in out AppendableCollection); procedure removeTheLastItemFrom ( theCollection : in out AppendableCollection); -- precondition: isNotEmpty( theCollection ); private type AppendableCollection is new AbstractAppendableCollection with null record; -- (with null record until I get round to implementing it!) end; with AbstractIterator_P; generic package AppendableCollection_P.ForwardsIterator_P is package ItemTypeAbstractIterator_P is new AbstractIterator_P (CollectionType => AppendableCollection, ItemType => ItemType ); use ItemTypeAbstractIterator_P; type ForwardsIterator is new AbstractIterator with private; function aNewIteratorFor ( theCollection : AppendableCollection ) return AbstractIterator'Class; function theCurrentItem ( theIterator : ForwardsIterator ) return ItemType; function atTheEnd ( theIterator : ForwardsIterator ) return Boolean; procedure advance ( theIterator : in out ForwardsIterator ); -- precondition : not(atTheEnd()) procedure reset ( theIterator : in out ForwardsIterator ); -- reset the state of the iterator to be that after creation private type ForwardsIterator is new AbstractIterator with null record; -- (with null record until I get round to implementing it!) end; -- similar child packages for BackwardsIterator etc. The above specifications compile but I have yet to write some bodies and check that this is really a workable scheme.