Ada Programlama Dili — Paketler (Packages)

mozgan
Ada Programlama Dili
14 min readJun 10, 2024

Bugünkü makalemizde modüler yapı başlığı altında bulunan paketlere değineceğiz. Fakat paket konusu Ada programlama dilinde büyük bir yer kapladığı için, bu yazımızda paket kullanımının yalnızca bir kısmına değindik ve şu soruları cevaplamaya çalıştık: Bir paket nasıl oluşturulur? Paketlerin kullanımı nasıldır? Hiyerarşik bir paket sistemi nasıl yapılır? Alt paketlerin kullanımı nasıl gerçekleştirilir? Özel paketler nedir? vb. Ayrıca makalenin daha iyi anlaşılabilmesi için örnek olarak tek bir paketi ele aldık ve bu paketin nasıl genişletilebildini anlatmaya çalıştık.

https://kulturveyasam.com/wp-content/uploads/2024/02/bal_petekleri_neden_altigen_03.jpg

Her ne kadar metot ve fonksiyon kullanarak program kodlarını modüler bir hale getirebilsek de, paketler ise bize bir üst yapı kurma olanağı sağlar. Daha açık bir ifadeyle söylemek gerekirse; paketler, türlerin, alt türlerin, sabitlerin ve alt programların anlamlı bir şekilde gruplandırılmasına imkân tanırlar. Bunun yanında bir paket daha küçük birimlere, yani alt paketlere de bölünebilir. Bu sayede daha organize edilmiş bir kod elde ederiz.

Bir paket, başlık (package header veya specification) ve gövde (package body) olmak üzere iki bölümden oluşur. Başlık kısmında, paket içerisinde kullanılacak olan türler, alt türler, değişkenler, metotlar, fonksiyonlar vb. bulunabilir. Gövde kısmında ise paketin sahip olduğu uygulama vardır. Ayrıca her gövde için bir başlık kısmı bulunmalıdır, ancak bunun tersi mecbur değildir. Örneğin; yalnızca türleri, sabitleri ve değişkenleri içeren bir paket için genellikle gövdeye gerek olmaz.

Sözdizimi

Yukarıda da bahsedildiği gibi bir paket, başlık ve gövde olmak üzere iki kısımdan oluşur. Başlık kısmı .ads uzantılı bir dosya içerisinde bulunurken, gövde kısmı ise .adb uzantılı bir dosyaya yazılır. Hal böyle olunca karşımıza birbirine çok benzeyen iki farklı sözdizimi çıkmaktadır.

Bir paketin başlık kısmına ait sözdizimi şu şekildedir:

-- <Package_Name>.ads

package <Package_Name> is
-- Başlık bölümü:
-- paket içerisinde kullanılacak değişkenler, sabitler, tür tanımları,
-- alt programlar vb. öğeler tanımlanır

-- NOT: Dışarıdan erişimin sağlandığı alan (public)

private
-- NOT: Dışarıdan erişimin kısıtlandığı alan (private)

end <Package_Name>;

Bu sözdiziminden anlaşılacağı üzere, bir paket başlığı içerisinde herkesin ulaşabileceği bir yer (public) olsa da kısıtlı bir alan (private) da mevcut. Kısıtlı alanda bulunanlara yalnızca o paket içerisinden erişim sağlanabilir ve böylece bulunduğu paketin gövdesinde kullanılabilirler. Böylece diyebiliriz ki paketler, veri gizlemenin, yani kapsüllemenin (encapsulation) yönetildiği yerlerdir.

Bir paketin gövde kısmına ait sözdizimi de aşağıdaki gibidir:

-- <Package_Name>.adb

package body <Package_Name> is
-- Gövde bölümü:
-- alt programlar icra edilir
end <Package_Name>;

Paketlerin gövde kısmında genellikle alt programlar bulunur. Tabii ki her bir alt program kendi içerisinde pek çok tür, alt tür, metot, fonksiyon vb. barındırabilir. Fakat bunlar yalnızca tanımlı oldukları alt programın kapsamında kalırlar.

Oluşturulan bir paketi diğer birimler içerisinde kullanabilmek için with anahtar kelimesine ihtiyaç vardır. Paketin bir öğesine de nokta (.) ayracı yardımıyla erişebiliriz. Noktanın solunda paketin adı, sağında ise erişilmek istenen öğe bulunur: <Paket_Adı>.<Paketin_Öğesi>. Yani bir paket, bir alan adını (namespace) da beraberinde getirir. Şayet paketin öğesine erişmek için her defasında nokta kullanımından kurtulmak istenirse, use anahtar kelimesinden yararlanılır: use <Paket_Adı>. Buna ek olarak hemen şunu da belirtelim; use anahtar kelimesinin etki alanı bulunduğu yere göre değişiklik gösterir. Daha açık bir şekilde ifade edecek olursak; eğer bir dosyanın başında use kullanılırsa, o paketin öğelerine erişmek için dosyanın tamamında nokta kullanımına gerek kalmaz. Şayet use anahtar kelimesi bir alt programın veya kod öbeğinin öğeler kısmındanda bulunursa, etki alanı yalnızca bulunduğu blok ile sınırlıdır. Bu çeşit farklı kullanımlar aşağıdaki örneklerde sunulmuştur. Dikkat edilmesini rica ederim.

Son olarak şunu da hatırlatmakta fayda var: GNAT derleyicisi kullananların dikkat etmesi gereken husus da bir paketin adı ile bulunduğu dosyanın adının aynı olması gerekmektedir. Aksi halde kodunuz her ne kadar sorunsuz derlense de derleme aşamasında devamlı bir uyarı ile karşılaşırsınız.

Kullanım Yöntemleri

Ada dilinde paket kullanımı çok yaygındır. Hatta diğer dillerde bulunan bir çok teknik paketler sayesinde gerçekleştirilir. Yani paketler, yazılımcının gereksinimine göre farklı şekillerde kullanılmaya olanak sağlarlar. Şimdi sırasıyla bu yöntemlerin bir kısmına değinelim.

Bir paket, programın her yerinden erişilebileceği en genel türleri, alt türleri, değişkenleri, sabitleri ve alt programları (metotlar ve fonksiyonlar) içerisinde barındırabilir. Ayrıca bu paketin gövde kısmı da olmayabilir. Yani tüm öğeler yalnızca .ads dosyası içerisinde bulunur. Buna ek olarak, bu tür kullanıma sahip paketlerde genellikle private kısmı da bulunmaz.

-- math.ads

package Math is

type Byte is mod 256;

PI : constant Float := 3.141_59;
E : constant Float := 2.718_28;
Catalan : constant Float := 0.915_96;

function Add (X, Y : Integer) return Integer is (X + Y);
function Sub (X, Y : Integer) return Integer is (X - Y);
function Mul (X, Y : Integer) return Integer is (X * Y);
function Div (X, Y : Integer) return Integer is (X / Y);

end Math;

Yukarıdaki örnekte de görüleceği üzere, Math adında bir paket oluşturulmuş; ve bu paketin içerisinde programın her yerinden erişime açık, en genel tanımlar ve alt programlar bulunuyor. Fakat burada dikkat edilmesi gereken husus da şudur; bu şekilde genel kullanıma sahip bir paket içerisinde değişken tanımlamak pek iyi bir fikir değildir. Çünkü global tanımlanmış bir değişken, program çalıştığı sürece pek çok yan etkiye neden olabilir.

Bir paket, başlık kısmında bulunan alt programların içeriğini gövde kısmına alınması suretiyle kütüphane gibi de kullanılabilir. Bu yöntem her ne kadar işletim sistemi seviyesinde bir kütüphane oluşturmaya olanak sağlasa da; burada bahsedilen olay, böyle bir paketin, bulunduğu uygulama içinde bir kütüphane gibi kullanımından öteye gitmiyor.

Eğer bir paketin başlık kısmında türlerin, alt türlerin, değişkenlerin, sabitlerin ve alt programların yalnızca tanımları bulunuyorsa, bu paketin bir de gövde kısmına ihtiyacı vardır. Örneğin, yukardaki kodda bulunan Add, Sub, Mul ve Div fonksiyonlarını başlık kısmında tanımlayabilir, bunların ne iş yaptıklarını da gövde kısmında yazabiliriz.

Daha kapsamlı bir örnek vermek gerekirse; farz edelim ki yukarıdaki örnekte bulunan Math paketini kütüphane olarak tasarlıyoruz. Ve buna ek olarak, karmaşık sayıları gösteren Complex adında bir tür tanımlamak istiyoruz. Fakat bu türün öğelerine direk erişimi de kısıtlamayı düşünüyoruz. O halde, Complex türünü paketimizin private kısmına yazabiliriz. Ayrıca Complex türünden değişkenler üretmek ve bazı aritmetik işlemleri yapabilmek için de kimi fonksiyonları yazılımcının kullanımına açmayı istiyoruz. O zaman Math kütüphanesi aşağıdaki gibi genişletilebilir ve başlık kısmı şu şekilde yazılabilir:

-- math.ads

package Math is

type Byte is mod 256;

PI : constant Float := 3.141_59;
E : constant Float := 2.718_28;
Catalan : constant Float := 0.915_96;

function Add (X, Y : Integer) return Integer;
function Sub (X, Y : Integer) return Integer;
function Mul (X, Y : Integer) return Integer;
function Div (X, Y : Integer) return Integer;

-- Complex türünün içeriğine erişim kısıtlı,
-- fakat bu türe ait değişken veya sabit oluşturulabilir
type Complex is private;

function Complex_Number (Re, Im : Float) return Complex;
function Re (Num : Complex) return Float;
function Im (Num : Complex) return Float;
function "+" (Left, Right : Complex) return Complex;
function "-" (Left, Right : Complex) return Complex;

private

type Complex is record
Re : Float := 0.0;
Im : Float := 0.0;
end record;

end Math;

Yukarıdaki kod içerisinde bulunan type Complex is private; deyiminin amacı, kendisinden sonra gelen fonksiyonlarda Complex türünü kullanabilmeye olanak sağlamak ve bunun yanında, Math paketini kullanan birisinin Complex türünden değişken veya sabit üretebilmesine de yardımcı olmak. Fakat bu türün öğelerine (yani Re ve Im) erişimin hala kısıtlı olduğu da unutulmamalı.

Math paketinin gövde kısmı da aşağıdaki gibi yazılabilir:

-- math.adb

package body Math is

function Add (X, Y : Integer) return Integer is (X + Y);
function Sub (X, Y : Integer) return Integer is (X - Y);
function Mul (X, Y : Integer) return Integer is (X * Y);
function Div (X, Y : Integer) return Integer is (X / Y);

function Complex_Number (Re, Im : in Float) return Complex is ((Re, Im));
function Re (Num : Complex) return Float is (Num.Re);
function Im (Num : Complex) return Float is (Num.Im);
function "+" (Left, Right : Complex) return Complex is
((Left.Re + Right.Re, Left.Im + Right.Im));
function "-" (Left, Right : Complex) return Complex is
((Left.Re - Right.Re, Left.Im - Right.Im));

end Math;

Şimdi ufak bir uygulama içerisinde tüm fonksiyonları test edelim. Ve bu sayede yukarıda teorik olarak anlatılan with ve use anahtar kelimelerinin kullanımlarını ve etki alanlarını da görmüş oluruz.

-- main.adb

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Assertions; use Ada.Assertions;

with Math;

procedure Main is

begin

begin
Assert (Math.Add (3, 2) = 5, "Add fonksiyonu hatalı!");
Assert (Math.Sub (1, 2) = -1, "Sub fonksiyonu hatalı!");
Assert (Math.Mul (-3, -2) = 6, "Mul fonksiyonu hatalı!");
Assert (Math.Div (9, -2) = -4, "Div fonksiyonu hatalı!");
end;

declare
use Math;

X : Complex := Complex_Number (1.0, 2.0);
Y : Complex;
begin
Y := Complex_Number (0.0, 2.0);

Assert (Re (X) = 1.0, "Re fonksiyonu hatalı!");
Assert (Im (X) = 2.0, "Im fonksiyonu hatalı!");

Assert (Re (X + Y) = 1.0, "Re için + operatörü hatalı!");
Assert (Im (X + Y) = 4.0, "Im için + operatörü hatalı!");

Assert (Re (Y - X) = -1.0, "Re için - operatörü hatalı!");
Assert (Im (Y - X) = 0.0, "Im için - operatörü hatalı!");

end;

end Main;

Bir paket, içerisinde pek çok alt paketi de barındırabilir. Bu şekil bir kullanım, hiyerarşik bir paket yapısını elde etme olanağı da bizlere sağlar.

Şimdi, yukarıdaki kodda Complex türü için Complex_Numbers adında bir alt paket oluşturmayı düşünelim. Bu durumda Math paketinin başlık kısmı şu hale gelecektir:

-- math.ads

package Math is

type Byte is mod 256;

PI : constant Float := 3.141_59;
E : constant Float := 2.718_28;
Catalan : constant Float := 0.915_96;

function Add (X, Y : Integer) return Integer;
function Sub (X, Y : Integer) return Integer;
function Mul (X, Y : Integer) return Integer;
function Div (X, Y : Integer) return Integer;

package Complex_Numbers is

type Complex is private;

function Complex_Number (Re, Im : Float) return Complex;
function Re (Num : Complex) return Float;
function Im (Num : Complex) return Float;
function "+" (Left, Right : Complex) return Complex;
function "-" (Left, Right : Complex) return Complex;

private

type Complex is record
Re : Float := 0.0;
Im : Float := 0.0;
end record;

end Complex_Numbers;

end Math;

Aynı şekilde, Math paketinin gövdesi de aşağıdaki gibi olacaktır:

-- math.adb

package body Math is

function Add (X, Y : Integer) return Integer is (X + Y);
function Sub (X, Y : Integer) return Integer is (X - Y);
function Mul (X, Y : Integer) return Integer is (X * Y);
function Div (X, Y : Integer) return Integer is (X / Y);

package body Complex_Numbers is

function Complex_Number (Re, Im : in Float) return Complex is ((Re, Im));
function Re (Num : Complex) return Float is (Num.Re);
function Im (Num : Complex) return Float is (Num.Im);
function "+" (Left, Right : Complex) return Complex is
((Left.Re + Right.Re, Left.Im + Right.Im));
function "-" (Left, Right : Complex) return Complex is
((Left.Re - Right.Re, Left.Im - Right.Im));

end Complex_Numbers;

end Math;

Artık Complex türüne ait fonksiyonlara Math.Complex_Numbers üzerinden erişebiliriz. O halde, aşağıdaki örneğe dikkat edilirse, use Math; deyimi değil, use Math.Complex_Number; kullanılmış:

-- main.adb

...
declare
use Math.Complex_Numbers;

X : Complex := Complex_Number (1.0, 2.0);
Y : Complex;
begin
...
end;
...

Dikkat ederseniz Math paketinin içeriği büyüdükçe satır sayısı da artıyor. Böyle bir paket içerisinde bir öğeyi aramak ve bulmak elbette ki zorlaşıyor. Zaten hiç bir yazılımcı da binlerce satırdan oluşan bir dosyayı okumak istemez :)

O halde, Math paketi içerisinde bulunan Complex_Numbers alt paketini ayırmak akla gelebilir. Ki şimdi yapacağımız şey de tam olarak budur. Tabii burada karşımıza yine dosya ismi için bir kural çıkmakta: bir alt paketin dosya adı, bulunduğu üst paketin adını içermeli ve ikisi arasında tire (-) kullanılmalı. Şu halde, Complex_Numbers için oluşturacağımız başlık ve gövde dosyaları math-complex_numbers.ads ve math-complex_numbers.adb olarak adlandırılacak. Şimdi, Complex_Numbers alt paketi bu dosyalar içerisinde bulunacağı için, derleyiciye de bunu bildirmek gerekecek ve bundan sonra alt paketimiz Math.Complex_Numbers olarak adlandırılacak. Üstelik ayrı dosya isimleri kullandığımızdan ötürü, Complex türüne ve fonksiyonlarına with Math; deyimi ile erişim sağlanamayacak. Artık alt paketin öğelerine erişebilmek için, örneğin main.adb dosyası içerisinde ek olarak with Math.Complex_Numbers; deyimi yazılacak. Yöntemin teorik kısmını anlattıktan sonra şimdi de Math paketinin ve Math.Complex_Numbers alt paketinin içeriklerine bir bakalım:

-- math.ads

package Math is

type Byte is mod 256;

PI : constant Float := 3.141_59;
E : constant Float := 2.718_28;
Catalan : constant Float := 0.915_96;

function Add (X, Y : Integer) return Integer;
function Sub (X, Y : Integer) return Integer;
function Mul (X, Y : Integer) return Integer;
function Div (X, Y : Integer) return Integer;

end Math;
-- math.adb

package body Math is

function Add (X, Y : Integer) return Integer is (X + Y);
function Sub (X, Y : Integer) return Integer is (X - Y);
function Mul (X, Y : Integer) return Integer is (X * Y);
function Div (X, Y : Integer) return Integer is (X / Y);

end Math;

Görüleceği gibi, Math paketi içerisinde Complex türüne ait hiç bir satır kalmamış; ve hepsi alt paketin dosyaları içerisine yazılmış:

-- math-complex_numbers.ads

package Math.Complex_Numbers is

type Complex is private;

function Complex_Number (Re, Im : Float) return Complex;
function Re (Num : Complex) return Float;
function Im (Num : Complex) return Float;
function "+" (Left, Right : Complex) return Complex;
function "-" (Left, Right : Complex) return Complex;

private

type Complex is record
Re : Float := 0.0;
Im : Float := 0.0;
end record;

end Math.Complex_Numbers;
-- math.complex_numbers.adb

package body Math.Complex_Numbers is

function Complex_Number (Re, Im : in Float) return Complex is ((Re, Im));
function Re (Num : Complex) return Float is (Num.Re);
function Im (Num : Complex) return Float is (Num.Im);
function "+" (Left, Right : Complex) return Complex is
((Left.Re + Right.Re, Left.Im + Right.Im));
function "-" (Left, Right : Complex) return Complex is
((Left.Re - Right.Re, Left.Im - Right.Im));

end Math.Complex_Numbers;

Şimdi, farz edelim ki yalnızca Complex_Numbers alt paketi için bir test yazmak istiyoruz. O halde, örneğin complex_test.adb adında bir dosya oluşturabilir ve bu alt pakete ait tüm testlerimizi buraya yazabiliriz:

-- complext_test.adb

with Ada.Assertions; use Ada.Assertions;
with Math.Complex_Numbers;

procedure complex_test is

use Math.Complex_Numbers;

X : Complex := Complex_Number (1.0, 2.0);
Y : Complex;

begin

Y := Complex_Number (0.0, 2.0);

Assert (Re (X) = 1.0, "Re fonksiyonu hatalı!");
Assert (Im (X) = 2.0, "Im fonksiyonu hatalı!");

Assert (Re (X + Y) = 1.0, "Re için + operatörü hatalı!");
Assert (Im (X + Y) = 4.0, "Im için + operatörü hatalı!");

Assert (Re (Y - X) = -1.0, "Re için - operatörü hatalı!");
Assert (Im (Y - X) = 0.0, "Im için - operatörü hatalı!");

end complex_test;

-- Derleme işlemi öncesi:
-- ❯ ls
-- complex_test.adb main.adb math-complex_numbers.adb math-complex_numbers.ads math.adb math.ads

-- Derleme işlemi:
-- ❯ gnatmake complex_test.adb
-- gcc -c complex_test.adb
-- gcc -c math.adb
-- gcc -c math-complex_numbers.adb
-- gnatbind -x complex_test.ali
-- gnatlink complex_test.ali

-- Derleme işlemi sonrası:
-- ❯ ls
-- complex_test* complex_test.ali main.adb math-complex_numbers.ads math-complex_numbers.o math.ads math.o
-- complex_test.adb complex_test.o math-complex_numbers.adb math-complex_numbers.ali math.adb math.ali

Yukarıdaki derleme işleminden de anlaşılacağı üzere, her ne kadar complex_test.adb dosyası içerisinde yalnızca Math.Complex_Numbers alt paketini kullanmış olsak da derleyici tüm paketi derlemiş. Bu noktada şunu söyleyebiliriz: her bir alt paket aslında ayrı ayrı derlenir. Fakat en nihayetinde en üst pakete ihtiyaç vardır. Bu sayede Math paketi için bir obje dosyası oluşturulur (math.o). Farklı bir şekilde anlatmak gerekirse; math.ads dosyası olmadan math-complex_numbers.ads ve math-complex_numbers.adb dosyaları derlenmez. En azından, aşağıdaki gibi boş dahi olsa bir math.ads dosyasına kesinlikle ihtiyaç vardır.

-- math.ads

package Math is
end Math;

Şimdi görüş açımızı biraz daha genişletelim ve yukarıdaki Math kütüphanesini büyütelim. Farz edelim ki geometrik işlemler için Math.Geometry adında bir alt pakete ihtiyacımız var. Aynı şekilde cebirsel işlemler için de Math.Algebra adında bir tane alt paket oluşturacağız. O halde, Complex_Numbers da cebir ile alakalı olduğu için Math.Algebra içerisinde bir alt paket olarak bulunacak. Şimdi Math paketinin ve alt paketlerinin başlık ve gövde dosyalarına sırasıyla bi bakalım:

-- math.ads

package Math is

type Byte is mod 256;

PI : constant Float := 3.141_59;
E : constant Float := 2.718_28;
Catalan : constant Float := 0.915_96;

Counter : Integer := 0;

end Math;

Görüleceği gibi math.ads dosyası içerisinde Byte türümüz ve sabitlerimiz bulunuyor. Ayrıca ek olarak bir de Counter adında değişken tanımlamışız. Add, Sub, Mul ve Div alt programları cebirsel işlemler olduğu için Math.Algebra alt paketi içerisine yazdık.

-- math-algebra.ads

package Math.Algebra is

function Add (X, Y : Integer) return Integer is (X + Y);
function Sub (X, Y : Integer) return Integer is (X - Y);
function Mul (X, Y : Integer) return Integer is (X * Y);
function Div (X, Y : Integer) return Integer is (X / Y);

Counter : Integer := Math.Counter;

end Math.Algebra;

Add, Sub, Mul ve Div alt programları basit birer fonksiyon olduğundan ötürü, bu fonksiyonların içerikleri math-algebra.ads dosyası içerisinde yazılmış. Demek oluyor ki, math-algebra.adb adında bir dosyaya ihtiyacımız olmayacak. Sonrasında Counter adında bir değişken tanımlanmış. Hatırlarsanız aynı isimde olan bir değişkeni math.ads dosyası içerisinde de tanımlamıştık. Fakat bu iki değişken herhangi bir çakışma oluşturmaz çünkü alt paketler de kendilerine ait bir alan adını (namespace) beraberinde getirirler. O halde diyebiliriz ki; Math.Counter ile Math.Algebra.Counter değişkenleri esasında birbirlerinden farklı değişkenlerdir.

-- math-algebra-complex_numbers.ads

package Math.Algebra.Complex_Numbers is

type Complex is private;

function Complex_Number (Re, Im : Float) return Complex;
function Re (Num : Complex) return Float;
function Im (Num : Complex) return Float;
function "+" (Left, Right : Complex) return Complex;
function "-" (Left, Right : Complex) return Complex;

private

type Complex is record
Re : Float := 0.0;
Im : Float := 0.0;
end record;

end Math.Algebra.Complex_Numbers;
-- math-algebra-complex_numbers.adb

package body Math.Algebra.Complex_Numbers is

function Complex_Number (Re, Im : in Float) return Complex is ((Re, Im));
function Re (Num : Complex) return Float is (Num.Re);
function Im (Num : Complex) return Float is (Num.Im);
function "+" (Left, Right : Complex) return Complex is
((Left.Re + Right.Re, Left.Im + Right.Im));
function "-" (Left, Right : Complex) return Complex is
((Left.Re - Right.Re, Left.Im - Right.Im));

end Math.Algebra.Complex_Numbers;

Yukarıdaki alt paketin adına dikkat edilirse Math.Algebra.Complex_Numbers olarak verilmiş; çünkü bu alt paketin Algebra içerisinde bulunacağını belirtmiştik. Aynı şekilde Algebra da Math paketi içerisinde bulunuyor. Bundan ötürü, Math.Algebra.Complex_Numbers alt paketinin başlık dosyası math-algebra-complex_numbers.ads, gövde dosyası ise math-algebra-complex_numbers.adb olarak adlandırılmış. Yani demek oluyor ki, hiyerarşik bir paket sisteminde her bir alt pakete ait dosya adları, kendisinin bulunduğu tüm üst paketlerin isimlerini içerisinde barındırır; ve her biri tire (-) işareti kullanılarak ayrılır.

Son olarak Geometry alt paketini de yazalım. Farz edelim ki bu alt paket de bazı basit fonksiyonları içerisinde barındırıyor. Örneğin dairenin alanını hesaplayan bir fonksiyon: Circle_Area. O halde bu alt paketin başlık dosyası şu şekilde olacak:

-- math-geometry.ads

package Math.Geometry is

function Circle_Area (R : Float) return Float is (PI * R * R);

end Math.Geometry;

Şimdi de tüm değişkenleri ve fonksiyonları test etmek istiyoruz ve aşağıdaki gibi main.adb dosyası oluşturuyoruz:

-- main.adb

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Assertions; use Ada.Assertions;

with Math.Geometry;
with Math.Algebra;
with Math.Algebra.Complex_Numbers;

procedure Main is

begin
Math.Counter := 1;
Put_Line ("Math.Counter: " & Math.Counter'Image);

Math.Algebra.Counter := 10;
Put_Line ("Math.Algebra.Counter: " & Math.Algebra.Counter'Image);

declare
use Math.Algebra;
begin
Assert (Add (3, 2) = 5, "Add fonksiyonu hatalı!");
Assert (Sub (1, 2) = -1, "Sub fonksiyonu hatalı!");
Assert (Mul (-3, -2) = 6, "Mul fonksiyonu hatalı!");
Assert (Div (9, -2) = -4, "Div fonksiyonu hatalı!");
end;

declare
use Math;
begin
Assert (Geometry.Circle_Area (1.0) = Math.PI, "Alan hesaplama hatalı!");
end;

declare
use Math.Algebra.Complex_Numbers;

X : Complex := Complex_Number (1.0, 2.0);
Y : Complex;
begin
Y := Complex_Number (0.0, 2.0);

Assert (Re (X) = 1.0, "Re fonksiyonu hatalı!");
Assert (Im (X) = 2.0, "Im fonksiyonu hatalı!");

Assert (Re (X + Y) = 1.0, "Re için + operatörü hatalı!");
Assert (Im (X + Y) = 4.0, "Im için + operatörü hatalı!");

Assert (Re (Y - X) = -1.0, "Re için - operatörü hatalı!");
Assert (Im (Y - X) = 0.0, "Im için - operatörü hatalı!");

end;

end Main;

Dikkat ederseniz main.adb dosyası içerisinde, öğesine erişilmek istenen tüm dosyalar with anahtar kelimesi ile yazılmış. Diyelim ki biz sadece with Algebra; yazarak Comlex_Numbers alt paketine de erişmek istiyoruz. O halde math-algebra.ads dosyası içerisinde aşağıdaki satır eklenir:

limited with Math.Algebra.Complex_Numbers;

Ada dilinde bulunan limited anahtar kelimesi pek çok yerde ve farklı anlamlarda karşımıza çıkar. Buraki manası ise ileride tanımlanacak olan bir alt paket ile yapılan bağlantıyı ifade eder. Yani, bizim örneğimiz üzerinden anlatmak gerekirse; Math.Algebra alt paketi içerisinde bulunan limited anahtar kelimesi, ileride tanımlanacak olan Math.Algebra.Complex_Numbers alt paketine bağımlı ve Complex_Numbers içerisinde bulunan bazı öğeler Algebra içerisinde kullanılacak anlamına gelir.

Özel Alt Paketler

Bir alt paketi, bulunduğu paketin dışarısından erişimine tamamen kapatmak için private package deyimi kullanılır. Örneğin, Math kütüphanesinde bulunan sabitleri Math.Constant içerisinde tanımlamak ve bu sabitleri dışarıdan erişimini kısıtlamak istiyoruz. O halde kütüphanemiz içerisinde aşağıdaki gibi math-constants.ads adında bir dosya oluşturabiliriz:

-- math-constants.ads

package Math.Constants is

PI : constant Float := 3.141_59;
E : constant Float := 2.718_28;
Catalan : constant Float := 0.915_96;

end Math.Constants;

Bu durumda Math.Geometry alt paketi için bir gövde de yazılmalı:

-- math-geometry.adb

with Math.Constants;

package body Math.Geometry is

function Circle_Area (R : Float) return Float is (Math.Constants.PI * R * R);

end Math.Geometry;

Bu sayede main.adb içerisinde, örneğin yukarıdaki gibi PI sabitine erişim kesinlikle gerçekleşmez.

Bitirirken

Ada programlama dilinde paket kullanımının çok kapsamlı olduğuna değinmiştik. Makalemizin daha anlaşılır olması için uzun uzun örneklere yer verildi. Ayrıca paket konusunun burada bitmediğini belirtmekte fayda var. Çünkü nesne yönelimli programlama tekniklerini yine paketler yardımıyla gerçekleştireceğiz.

--

--