Paket (2) with LängdKonstanter; use LängdKonstanter; procedure Main is Ett huvudprogram som infogar detta paket: Paket (1) Ett paket med en praktisk uppsättning konstanter: package LängdKonstanter is -- Alla värden uttryckta i meter: inch : constant Float := 0.0254; foot : constant Float := 12.0 * inch; mile : constant Float := 5280.0 * foot; fermi : constant Float := 10.0E-15; ångström : constant Float := 10.0E-10; nautisk_mil : constant Float := 6076.0 * foot; -- au : Astronomisk enhet au : constant Float := 1.4960E+11; ljusår : constant Float := 9.4607E+15; end LängdKonstanter; längd : Float; -- i meter. Put(längd * foot, 0, 3, 0); Put("fot."); New_Line; end Main; procedure Main is inch : constant Float := 0.0254; foot : constant Float := 12.0 * inch; mile : constant Float := 5280.0 fermi : constant Float := 10.0E-15; ångström : constant Float := 10.0E-10; nautisk_mil : constant Float := 6076.0 au : constant Float := 1.4960E+11; ljusår : constant Float := 9.4607E+15; längd : Float; -- i meter. Put(längd * foot, 0, 3, 0); Put("fot."); New_Line; end Main; Det fungerar som om det från början hade stått Paket (3) Ett paket som definierar några typer och konstanter: package TwoDimTypes is type Point is record x, y: Float; type Circle is record center : Point; radius : Float; type Rectangle is record upper_left : Point; width : Float; height : Float; Origo : constant Point := (0.0, 0.0); UnitCircle : constant Circle := (Origo, 1.0); end TwoDimTypes; Paket (4) Ett användande huvudprogram. Det gör with på paketet, men inte use! with TwoDimTypes; procedure ppp is P1, P2 : TwoDimTypes.Point; Rect : TwoDimTypes.Rectangle; C1 : TwoDimTypes.Circle := TwoDimTypes.UnitCircle; end ppp; Paketet tas med, men dess innehåll är inte direkt synligt! Man måste då ange paketnamn. före varje namn ur paketet! use ser till att paketet öppnas så att alla dess beståndsdelar blir direkt synliga. Skrivsättet paketnamn.paketkomponent är nödvändigt bara när olika paket innehåller komponenter med samma namn!
Paket (7) Detta är bodyn ( kroppen ) till paketet Pack. Här finns subrutinerna i sin fullständighet! Filen skall ha namnet paketnamn.adb. package body Pack is the_year : Natural) return is return (the_day, the_month, the_year); end Make; procedure GetNext(the_date : in out ) is end GetNext; Paket (8) Fortsättninen av Pack s body: procedure GetNextWeekday(the_weekday : in out Weekday) is end GetNextWeekday; function IsLeapyear(the_year : Natural) return Boolean is end IsLeapYear; Paket (5) Ett annat paket Pack som definierar såväl typer och konstanter som subrutiner! Paketet skall då bestå av två filer. Först paketets specifikation: package Pack is type Weekday is (Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday); subtype DayNr is integer range 1.. 31; subtype MonthNr is integer range 1.. 12; type is record Day : DayNr; Month : MonthNr; Year : Natural; Paket (6) Fortsättning: I paketspecifikationen kan bara subrutiners specifikation förekomma! StartOfWeek : constant Weekday := Weekday first; StartOf2000 : constant := (1, 1, 2000); the_year : Natural) return ; procedure GetNext(the_date : in out ); procedure GetNextWeekday(the_weekday : in out Weekday); function IsLeapyear(the_year : Natural) return Boolean; function ToString(the_date : ) return String; end Pack;
Paket (9) Slutet av Pack s body. Den första funktionen ToString finns inte i paketets specifikation. Den är då användbar (synlig) bara i denna paketbody! function ToString(n : Natural) return String is S : String := Image(n); return S(2.. S Last); end ToString; function ToString(the_date : ) return String is return ToString(the_date.Day) & / & ToString(the_date.Month) & & ToString(the_date.Year); end ToString; end Pack; Paket (10) En ny variant: Detta paket har även en privat del i specifikationen: package Pack2 is type Weekday is (Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday); Paket (11) Den privata delen av Pack2 gömmer datatypens utseende för användande program: function IsLeapyear(the_year : Natural) return Boolean; function ToString(the_date : ) return String; function DayOf(the_date : ) return DayNr; function MonthOf(the_date : ) return MonthNr; function YearOf(the_date : ) return Natural; private type is record Day : DayNr; Month : MonthNr; Year : Natural; end Pack2; subtype DayNr is integer range 1.. 31; subtype MonthNr is integer range 1.. 12; type is private; -- Bara typens namn!! StartOfWeek : constant Weekday := Weekday first; StartOf2000 : constant := (1, 1, 2000); the_year : Natural) return ; procedure GetNext(the_date : in out ); procedure GetNextWeekday(the_weekday : in out Weekday); Paket (12) Synlighet mellan paket och användande program. Paketets specifikation publik del privat del Användande program Vet alltså bara om vad som finns i paketets publika del! Paketets body Inget del av paketet vet alltså något om vad som finns i det användande programmet!
Paket (13) - deklaration av generiskt paket: generic type is private; package KöPack is type Kö is private; procedure Köa(E : ; K : in out Kö); procedure Hämta(K : in out Kö; E : in out ; ÄrTom : in out Boolean); private Max : constant := 1000; type IndexTyp is 1.. Max; type Lista is array(indextyp) of ; type Kö is record Sista : := 0; Element : Lista; end KöPack; En body också, förstås. Men den visas inte här. KöPack är ett sk generiskt paket, ett ofullständigt och i sig oanvändbart paket, som fungerar som en mall för att skapa riktiga paket. Typnamnet ska betraktas som en slags parameter. Paket (14) - Instatiering av generiskt paket: Paketmallen KöPack KöPack är bara en mall för hur andra paket ska skapas - det kan inte användas som det är. Typnamnet är bara ett parameternamn och måste ersättas med ett verkligt typnamn i en kopia av mallen. Det gör man med t ex dessa konstruktioner, sk instantieringar: package IntKöande is new KöPack(); package Köande is new KöPack(); Man får då två nya, verkliga paket, med namnen IntKöande resp Köande, där har ersatts av de verkliga typnamnen resp. Det verkliga paketet IntKöande Det verkliga paketet Köande De här paketen är vad man kallar instanser av KöPack och de kan nu användas som vanliga paket. Paket (15) - Instantiering av generiskt paket, exempel: with KöPack; procedure MyMain is type is -- enligt förut, t ex -- Instanser av mallen anpassade för -- s resp s skapas: package IntKöande is new KöPack(); package Köande is new KöPack(); use IntKöande, Köande; -- En kövariabel för vardera typen. Eftersom -- typnamnet Kö finns i båda paketen måste man -- ange vilket pakets Kö som avses: INTKÖ : IntKöande.Kö; DATEKÖ : Köande.Kö; D : := (8, 2, 2006); -- Ett datum; -- Nu kan - och -värden köas! -- Typen på parametrarna avgör vilken -- av de två Köa-procedurerna som väljs: Köa(12, INTKÖ); Köa(D, DATEKÖ); Paket (16) - Sammanfattning Ett paket innehåller helt enkelt en samling deklarationer. finns i en eller två egna filer för sig. Filens/filernas förnamn skall vara detsamma som paketets namn. består av två filer om den innehåller subrutiner, en enda fil om den inte innehåller subrutiner: - i paketets specfikationsfil (.ads) finns vid behov specifikationer (enbart!) av subrutiner, plus andra former av deklarationer. Denna fil finns alltid. - i paketets body-fil (.adb) skall subrutinerna från specifikationsfilen finnas i fullständig form. - bodyfilen kan dessutom innehålla andra deklarationer. kan inkluderas i ett annat program med with, och dess synliga innehåll kan sedan göras direkt åtkomligt med use. vet aldrig någonting om det program i vilket det inkluderas. kan också ha en privat - osynlig - del i specifikationen. kan dessutom vara generiskt. Det program som inkluderar ett paket vet ingenting om innehållet i paketets body. Det är alltid osynligt. vet heller inget om innehållet i paketspecifikationens eventuella privata del. kan alltså bara utnyttja det som finns i paketspecifikationens synliga del. måste skapa en konkret kopia (en instans) om paketet är generiskt. Endast en konkret paketinstans kan use:as.
Typen String (1) Den är en sk unconstrained array (array med obestämda indexgränser)! Tänkt deklaration (om den inte redan funnes!): type String is array(positive range <>) of Character; Strängliteraler: "Summa: " Strängvariabler: har (den underförstådda) typen array(1.. 7) of Character; QM : String := "? "; kan sedan bara ges nya strängvärden med exakt 2 tecken. S1 : String(1.. 12); kan bara ges strängvärden med exakt 12 tecken: S1 := "Pettersson "; Subtyper: subtype NameType is String(1.. 30); subtype ThreeLetter is String(1.. 3); Typen String (2) - operationer S2 : String (1.. 11); Ch : Character; T3 : ThreeLetter; Konkatenering (hopslagning) med operatorn & S2 := "Hej och " & "hå!"; put("vanligaste bokstaven är " & Ch); Slicing - delföljd av tecken: put(s2(index.. index + 4)); T3 := S2(3.. 5); T3 := S2(S2 last - 2.. s2 last); S2 := S2(2.. s2 last) & s2(1); S2(5.. 7) := " & "; Alla jämförelser (=, /=, <, ) kan också användas! NB! En generalisering: Konkatenering, slicing och jämförelser kan användas på alla endimensionella arraytyper med element av enkel typ! Typen String (3)- subrutiner Variabler, konstanter, subtyper måste ha fixerad längd! Men parametrar till subrutiner, värden av funktioner tillåts vara av den obegränsade typen String! function Clip(s : String) return String is for index in reverse s range loop if s(index) /= then return s(1.. index); end if; end loop; return ""; end Clip; Kan nu anropas med strängar av olika längd: Clip("Hejsan ") Clip("OK") Värdena har oförutsägbar längd - icke fix. Men tilldelning av värdet till en variabel funkar bara om längden av värdet stämmer med variabelns deklarerade längd! Text := Clip("Hejsan "); -- tveksamt! Däremot fungerar alltid t ex Put(Clip("Hejsan ")); eftersom Put s parameter också är en obegränsad String!