Modüller ve Kütüphaneler
D programlarını ve kütüphanelerini oluşturan en alt yapısal birimler modüllerdir.
D'nin modül kavramı çok basit bir temel üzerine kuruludur: Her kaynak dosya bir modüldür. Bu tanıma göre, şimdiye kadar deneme programlarımızı yazdığımız tek kaynak dosya bile bir modüldür.
Her modülün ismi, dosya isminin .d uzantısından önceki bölümü ile aynıdır; ve kaynak dosyanın en başına yazılan module anahtar sözcüğü ile belirtilir. Örneğin bir kaynak dosyanın isminin "kedi.d" olduğunu varsayarsak:
module kedi; class Kedi { // ... }
module satırı isteğe bağlıdır. Yazılmadığı zaman, otomatik olarak dosyanın isminin .d'den önceki bölümü kullanılır.
Dosya ve modül isimleri
D programlarını Unicode olarak oluşturma konusunda şanslıyız; bu, hangi ortamda olursa olsun geçerlidir. Ancak, dosya sistemleri konusunda aynı serbesti bulunmaz. Örneğin Windows işletim sistemlerinin standart dosya sistemleri dosya isimlerinde büyük/küçük harf ayrımı gözetmezken, Linux sistemlerinde büyük/küçük harfler farklıdır. Ayrıca çoğu dosya sistemi, dosya isimlerinde kullanılabilecek karakterler konusunda kısıtlamalar getirir.
O yüzden, programlarınızın taşınabilir olmaları için dosya isimlerinde yalnızca ASCII küçük harfler kullanmanızı öneririm. Örneğin yukarıdaki Kedi sınıfı ile birlikte kullanılacak olan bir Köpek sınıfının modülünün dosya ismini "kopek.d" olarak seçebiliriz.
Bu yüzden modülün ismi de ASCII harflerden oluşur:
module kopek; // ASCII harflerden oluşan modül ismi class Köpek // Unicode harflerden oluşan program kodu { // ... }
Paketler
Modüllerin bir araya gelerek oluşturdukları yapıya paket denir. D'nin paket kavramı da çok basittir: Dosya sisteminde aynı klasörde bulunan bütün modüller aynı pakedin parçası olarak kabul edilirler. Pakedi içeren klasörün ismi de modül isimlerinin baş tarafını oluşturur.
Örneğin yukarıdaki "kedi.d" ve "kopek.d" dosyalarının "hayvan" isminde bir klasörde bulunduklarını düşünürsek, modül isimlerinin başına klasör ismini yazmak, onları aynı pakedin modülleri yapmaya yeter:
module hayvan.kedi; class Kedi { // ... }
Aynı şekilde kopek modülü için de:
module hayvan.kopek; class Köpek { // ... }
Paket isimleri dosya sistemi klasörlerine karşılık geldiği için, iç içe klasörlerde bulunan modüllerin paket isimleri de o klasör yapısının eşdeğeridir. Örneğin "hayvan" klasörünün altında bir de "omurgalilar" klasörü olsa, oradaki bir modülün paket ismi bu klasörü de içerir:
module hayvan.omurgalilar.kedi;
Kaynak dosyaların ne derece dallanacağı programın büyüklüğüne ve tasarımına bağlıdır. Küçük bir programın bütün dosyalarının tek bir klasörde bulunmasında bir sakınca yoktur. Öte yandan, dosyaları belirli bir düzen altına almak için klasörleri gerektiği kadar dallandırmak da mümkündür.
Modüllerin programda kullanılmaları
Şimdiye kadar çok kullandığımız import anahtar sözcüğü, bir modülün başka bir modüle tanıtılmasını, ve o modül içinde kullanılabilmesini sağlar:
import std.cstream;
import'tan sonra yazılan modül ismi, eğer varsa, paket bilgisini de içerir. Yukarıdaki koddaki std., standart kütüphaneyi oluşturan modüllerin std isimli pakette bulunduklarını gösterir.
Benzer şekilde, hayvan.kedi ve hayvan.kopek modülleri bir "deneme.d" dosyasında şu şekilde bildirilir:
module deneme; // bu modülün ismi import hayvan.kedi; // kullandığı bir modül import hayvan.kopek; // kullandığı başka bir modül void main() { auto kedi = new Kedi; auto köpek = new Köpek; }
Not: Aşağıda anlatıldığı gibi, yukarıdaki programın derlenip oluşturulabilmesi için o modül dosyalarının da bağlayıcıya derleme satırında bildirilmeleri gerekir.
Modüllerin dosya sistemindeki yerleri
Modül isimleri dosya sistemindeki dosyalara bire bir karşılık geldiği için; derleyici, bir modül dosyasının nerede bulunduğunu modül ismini klasör ve dosya isimlerine dönüştürerek bulur.
Örneğin yukarıdaki programın kullandığı iki modül, "hayvan/kedi.d" ve "hayvan/kopek.d" dosyalarıdır. Dolayısıyla, yukarıdaki dosyayı da sayarsak bu programı oluşturmak için üç modül kullanılmaktadır.
Kısa ve uzun isimler
Programda kullanılan isimler, paket ve modül bilgilerini de içeren uzun halde de yazılabilirler. Bunu, Kedi sınıfının tür ismini kısa ve uzun yazarak şöyle gösterebiliriz:
auto kedi0 = new Kedi; auto kedi1 = new hayvan.kedi.Kedi; // üsttekinin aynısı
Normalde uzun isimleri kullanmak gerekmez. Onları yalnızca olası karışıklıkları gidermek için kullanırız. Örneğin iki modülde birden tanımlanmış olan bir ismi kısa olarak yazdığımızda, derleyici hangi modüldekinden bahsettiğimizi anlayamaz.
Hem hayvan modülünde hem de arabalar modülünde bulunabilecek Jaguar isimli iki sınıftan hangisinden bahsettiğimizi uzun ismiyle şöyle belirtmek zorunda kalırız:
import hayvan.jaguar; import arabalar.jaguar; // ... auto karışıklık = new Jaguar; // ← derleme HATASI auto hayvanım = new hayvan.jaguar.Jaguar; // ← derlenir auto arabam = new arabalar.jaguar.Jaguar; // ← derlenir
Modüllerdeki tanımların programa dahil edilmesi
import anahtar sözcüğü, belirtilen modülün programın parçası haline gelmesi için yeterli değildir. import, yalnızca o modüldeki olanakların bu kaynak kod içinde kullanılabilmelerini sağlar. O kadarı, ancak kaynak kodun derlenebilmesi için gereklidir.
Yukarıdaki programı yalnızca "deneme.d" dosyasını kullanarak oluşturmaya çalışmak yetmez:
$ dmd deneme.d -w
deneme.o: In function `_Dmain':
deneme.d:(.text._Dmain+0x4): undefined reference to
`_D6hayvan4kedi4Kedi7__ClassZ'
deneme.d:(.text._Dmain+0xf): undefined reference to
`_D6hayvan5kopek6Köpek7__ClassZ'
collect2: ld returned 1 exit status
--- errorlevel 1
Not: Derleyici uyarılarını etkinleştiren -w ayarını da her zaman için kullanmanızı öneririm.
O hata mesajları bağlayıcıdan gelir. Her ne kadar anlaşılmaz isimler içeriyor olsalar da; yukarıdaki hata mesajları, programda kullanılan bazı tanımların bulunamadıklarını bildirir.
Programın oluşturulması, perde arkasında çağrılan bağlayıcının görevidir. Derleyici tarafından derlenen modüller bağlayıcıya verilir; ve program, bağlayıcının bir araya getirdiği parçalardan oluşturulur.
Bu yüzden; programı oluşturan bütün parçaların derleme satırında belirtilmeleri gerekir. Yukarıdaki programın oluşturulabilmesi için, kullandığı "hayvan/kedi.d" ve "hayvan/kopek.d" dosyaları da derleme satırında bildirilmelidir:
$ dmd deneme.d hayvan/kedi.d hayvan/kopek.d -w
Modülleri derleme satırında her program için ayrı ayrı belirtmek yerine, onları kütüphaneler içinden de kullanabiliriz.
Kütüphaneler
Modül tanımlarının derlendikten sonra bir araya getirilmelerine kütüphane adı verilir. Kütüphaneler kendileri program olmadıkları için; programların başlangıç işlevi olan main, kütüphanelerde bulunmaz. Kütüphaneler yalnızca işlev, yapı, sınıf, vs. tanımlarını bir araya getirirler. Daha sonra program oluşturulurken programın diğer modülleriyle bağlanırlar.
Kütüphane oluşturmak için dmd'nin -lib seçeneği kullanılır. Oluşturulan kütüphanenin isminin hayvan olmasını sağlamak için -of seçeneğini de kullanırsak, yukarıdaki "kedi.d" ve "kopek.d" modüllerini içeren bir kütüphane şu şekilde oluşturulabilir:
$ dmd hayvan/kedi.d hayvan/kopek.d -lib -ofhayvan -w
Konsoldan çalıştırılan o komut, belirtilen .d dosyalarını derler ve bir kütüphane dosyası olarak bir araya getirir. Çalıştığınız ortama bağlı olarak kütüphane dosyasının ismi farklı olacaktır. Örneğin Linux ortamlarında kütüphane dosyalarının uzantıları .a olur: hayvan.a
Program oluşturulurken artık "hayvan/kedi.d" ve "hayvan/kopek.d"nin ayrı ayrı bildirilmelerine gerek kalmaz. Onları içeren kütüphane dosyası tek başına yeterlidir:
$ dmd deneme.d hayvan.a -w
Yani o komut, daha önce kullandığımız şu komutun eşdeğeridir:
$ dmd deneme.d hayvan/kedi.d hayvan/kopek.d -w
Bir istisna olarak, şimdiye kadar çok yararlandığımız Phobos modüllerini içeren standart kütüphanenin açıkça bildirilmesi gerekmez. O kütüphane, programa otomatik olarak dahil edilir. Yoksa normalde onu da örneğin şu şekilde belirtmemiz gerekirdi:
$ dmd deneme.d hayvan.a /usr/lib/libphobos2.a -w
Not: Phobos kütüphane dosyasının yeri ve ismi sizin ortamınızda farklı olabilir.
D.ershane
Forum
Wiki
Projeler
Tanıtım
İletişim
Hakları