Arayüz (yazılım)

Nesne yönelimli programlama dillerinde arayüz, değişik sınıflardan nesnelerin kategorize edilmesini sağlayan bir soyut tür çeşitidir. Tanımlanmakta olan kategorinin birbirleriyle alakasız sınıfları ortak bir çatı altında toplaması nedeniyle, arayüz tanımları, soyut sınıfların aksine, listeledikleri iletilerin gerçekleştirim ayrıntısı olan herhangi bir bilgi içeremezler. Dolayısıyla, bir arayüz tanımı iletilere karşılık gelen bir altyordam gövdesi veya altalan tanımı içeremez. Bir başka açıdan bakarsak, arayüz tanımında yer alan programlama öğelerinin zaman içinde değişme olasılığı düşük öğeler olması gerekir. Buna göre, arayüz tanımları gerçekleştirimci ile kullanıcının paylaştığı ve sabit olma özelliği bulunan altyordam imzaları ile simgesel sabit tanımlarını barındırabilir.

Kullanılan programlama dili tarafından doğrudan desteklenmediği durumlarda arayüz kavramı, altyordam gövdeleri içermeyen ve altalan barındırmayan bir soyut sınıf tanımı ile benzetilebilir. Soyut sınıf kavramının doğrudan desteklenmediği yordamsal dillerde ise, arayüzde bulunması beklenen programlama öğelerinin başlık dosyası benzeri bir dosyada toplanması sağlanarak arayüz kavramına öykünülebilinir. Ancak, derleyici desteğinin bulunmaması nedeniyle, her iki kullanımın da hataya açık olduğu unutulmamalıdır.

Sınıf kavramı ve kalıtlama ilişkisinin sınıfları sıradüzenine koyarak bir terminoloji oluşturmasına benzer bir şekilde, arayüz kavramı ve gerçekleştirme ilişkisi de sınıfları kategorilere ayırır. Herhangi bir arayüzü gerçekleştiren sınıflar, arayüzün tanımladığı kategoriye ait sayılır ve bu sınıfların nesneleri gerçekleştirilen arayüzün tutacağı ile kullanıldıklarında, aynı kategoride bulundukları için, çokbiçimli bir şekilde kullanılabilirler.

Ne kastedildiği sıklıkla kullanılan bir işlemle daha iyi anlaşılacaktır: sıralama. Bir grup verinin belirli bir öncelik-sonralık ilişkisine uygun olarak yeniden düzenlenmesi şeklinde tanımlanabilecek sıralama işlemi, söz konusu verilerin karşılaştırılabilir olmasını gerektirir. Zira, hangi verinin önce, hangi verinin sonra geleceği ancak karşılaştırma ile anlaşılabilir. Sıralanmak istenebilecek verilerin çeşitliliği düşünüldüğünde, karşılaştırma işleminin üstsınıfta yapılacak dinamik iletimli bir atyordam tanımının altsınıflarda ezilmesi ile gerçekleştirilemeyeceği görülür. Çünkü, böylesine bir çözüm üstsınıf ve altsınıflar arasında bir benzerlik ilişkisini gerektirir. Halbuki, birbiriyle alakasız pek çok kavram karşılaştırma işlemini desteklemek durumunda kalabilir. Karşılaştırma işleminin sınıf sıradüzeninin kök sınıfına taşınması da bir çare olmayacaktır; böylesine bir uygulama, matemetikteki matrisler gibi karşılaştırılamaz değerlerin de karşılaştırılabilir olduğu algısına neden olacaktır. Gerçek çözüm, karşılaştırılabilirlik kategorisine karşılık gelen bir arayüzün tanımlanması ve isteyen sınıfların bu arayüzü gerçekleştirmesinden geçer.

Yazılım geliştirmede arayüz kavramının temel kullanım amacı standart oluşturmaktır. Birbirini tamamlayan bileşenlerin bağımsız bir biçimde geliştirilmesine olanak tanımak ve aynı işlevi gören bileşenlerin tak-çıkar mantığıyla birbirinin yerine kullanılmasını kolaylaştırmak için böylesine bir yaklaşım zorunludur. Bu sayede, pazardan alınacak hazır bileşenler ve bileşenlerin paralel geliştirilmesinin yardımıyla daha güvenilir ürünlerin daha hızlı geliştirilmesi mümkün olacaktır. Bu, aşağıdaki zaman sıralamasına göre verilmiş etkinliklerden daha iyi anlaşılacaktır.

Dikkat edilecek olursa, Ü1'in piyasaya sürülmesinden sonra Ş3 tarafından geliştirilen B1 bileşeni sorun olmaksızın kullanılabilmektedir. Aynı şekilde, Ü1'in performansı geliştirilmiş uyarlaması da müşterinin daha önceden geliştirdiği yazılımın içinden rahatlıkla kullanılmaktadır. Geleceğe yapılan bu yolculukların her iksi de, arayüz tanımları sayesinde mümkün olmaktadır. Bunu, tadilat geçiren bir evin bölüm bölüm değiştirilmesine benzetebiliriz: doğramaların değiştirilmesi için evin yıkılıp yeniden yapılması gerekmez; aynı standarda uygun üretilen doğramanın eskisinin yerine takılması yeterli olacaktır.

Sınıfların ortak paydası olarak tanımlanması, arayüzlerdeki iletilerin çokbiçimli olarak kullanılabilmesini olanaklı kılar; arayüz tutacağı yoluyla gönderilecek iletiler, tutacağın temsil ettiği nesnenin sınıfındaki ilişkin gerçekleştirimin kullanılmasına neden olacaktır. Yandaki şekilden izleyecek olursak, nesneye gönderilecek iletiler öncelikle arayüz tutacağının eleğinden geçer. Arayüz türünde listelenmeyen iletiler derleyici tarafından reddedilecektir. Derleyici denetiminden geçen programın çalıştırılması sırasında ise, denetim akışının ileti gönderiminin yapıldığı yere gelmesi arayüz tutacağının gösterdiği nesnenin sınıfındaki—gerçekleştirilmiş veya kalıtlanmış—aynı imzaya sahip altyordamın çağrılmasına neden olur. Arayüz tutacağının gösterdiği nesnenin türünün, tutacak türünü doğrudan veya dolaylı bir biçimde gerçekleştiren bir sınıf olması zorunludur.

Arayüz gerçekleştirme ve arayüz tutacağının bu şekilde kullanılması, sınıf kalıtlama ve üstsınıf tutacağının kullanılması ile gelen çokbiçimliliğin getirdiği avantajları getirir. Arayüzdeki iletileri kullanarak yazılmış kod, arayüzü gerçekleştiren tüm sınıflar için çalışacak ve böylece aynı iskelete sahip kod parçalarının değişik sınıflar için tekrar tekrar yazılmasının önüne geçilmiş olacaktır. Bu ise, kodda yapılması istenen bir değişikliğin tek bir yerde yapılması anlamına gelir ki, kodun yeniden kullanımını sağlayan böylesine bir yaklaşım kod bakımını da kolaylaştıracaktır.

Kimi programlama dilleri arayüz kavramını dildeki bir yapı ile doğrudan desteklerken, diğerleri var olan yapıların disiplinli bir biçimde kullanılması yoluyla dolaylı olarak destekler. Takip eden alt bölümlerde her iki gruba dair örnekler verilmektedir. Dikkat edilecek olursa, ne şekilde desteklenirse desteklensin, arayüz tanımında herhangi bir gerçekleştirim ayrıntısının ele verilmediği, kullanıcı ile paylaşılan programlama öğelerinin—altyordam imzaları ve simgesel sabitler—değişmesi düşük olasılıklı öğeler olduğu görülecektir. Bu kısıtlamanın temelinde arayüzün kullanıcı kodu ile gerçekleştirimci arasında bir sözleşme olması özelliği ve gerçekleştirimcinin yapacağı değişikliklerin kullanıcı kodunda değişikliklere yol açma ihtimalini en aza indirmek isteği yatar.

Arayüz kavramını interface yapısı ile doğrudan destekleyen Java'da programcının yapacağı olası bir hata kavramdan haberdar derleyici sayesinde önlenir. Programlama dili standardındaki tanımlara uygun gerçekleştirilmiş derleyiciler, metot gövdesi ve altalan tanımı gibi gerçekleştirim ayrıntısı olarak addedilen programlama öğelerinin arayüze konulmasına izin vermez. Ayrıca, standart görevi görme ve kullanıcı kodu ile gerçekleştirimci arasında sözleşme tanımlama özelliklerinin bir sonucu olarak, arayüz tanımında yer alan tüm öğelerin public erişime sahip olduğu kabul edilir. Dolayısıyla, erişim niteleyicilerinin konulmasına gerek yoktur.

Arayüz tanımının derlenip sınıf yolu üzerinde uygun bir yere konulması sonrasında yapılması gereken, söz konusu kategoriye giren kavramların karşılığı olan sınıflarda bu arayüzün, belki de diğer arayüzlerle birlikte, gerçekleştirilmesidir. Bu noktada, arayüz(ler) ve sınıf arasındaki gerçekleştirme ilişkisinin bir taahhüt olduğu ve arayüz(ler)de listelenen tüm iletilerin gerçekleştirilmesi gerektiği unutulmamalıdır.

Arayüz kavramını doğrudan desteklemeyen C++ programlama dilinde programcıların belirli kurallara uyulan sınıf tanımlarıyla bu eksiği gidermeleri mümkündür. Öncelikle, altyordam gövdelerinin sağlanmaması koşulu, tüm fonksiyon tanımlarının dinamik iletimli boş fonksiyonlar (İng., pure virtual) olarak yapılması gerektiği anlamını taşır. Bu koşula uyulmaması, yapılmakta olan tanımı soyut/somut sınıf tanımına dönüştürür. Bir diğer önemli nokta ise, arayüzdeki tüm öğelerin kamuya açık ilan edilmesinin sonucudur: sınıf tanımının hemen başına public: konulması bir alışkanlık haline getirilmeli ve gerçekleştirim ayrıntısı olmanın habercisi diğer erişim niteleyicilerinden kaçınılmalıdır. Ayrıca, kullanıcı ile paylaşılacak olan arayüz tanımının C++ kaynak dosyası yerine başlık dosyasına konulması da iyi bir alışkanlık olacaktır.

Tanımların tamamlanması ve ilişkin başlık dosyalarının kütük dizgesinde uygun yerlere konulması sonrasında sıra arayüzlerin gerçekleştirimine gelir. Arayüz kavramını desteklemeyen C++, doğal olarak, gerçekleştirme ilişkisinden de haberdar değildir. Dolayısıyla, gerçekleştirme ilişkisi yerine kalıtlama ilişkisini koymamız gerekecektir.

Arayüz ve bu arayüzü gerçekleştiren sınıfın kullanımına gelindiğinde bir noktanın unutulmaması yararlı olacaktır. Dinamik iletimli fonksiyonların çokbiçimli kullanılabilmesi için nesnelerin referans veya gösterici aracılığıyla kullanılması gerekir. Aksi takdirde, tüm çağrılar çalışma öncesinde bağlanacak ve kodun çokbiçimli kullanılması söz konusu olmayacaktır.

Yordamsal bir dil olan C, nesne paradigmasının gerektirdiği en temel kavramları dahi desteklemez. Dolayısıyla, sınıf, arayüz gibi dil düzeyi kavramların işletim dizgesi kavramı olan dosyadan yararlanarak gerçekleştirilmesi zorunludur. Genel strateji, C++'da uygulanan ile aynıdır: başlık dosyasında tanımlanan arayüzün C dosyasında gerçekleştirilmesi. Arayüz tanımında, gerçekleştirim ayrıntısı ele vermemek adına, dinamik iletimli çağrılacak fonksiyonların adreslerini tutan yapının dışında tanım verilmemeli, statik iletimli çağrılacak fonksiyonların extern ile nitelenerek verilen deklarasyonu ile yetinilmelidir. Ayrıca, fonksiyonların işleyeceği ortak bir bellek bölgesi söz konusu ise, bunun tanımının da deklarasyon ile geçiştirilmesi ve asıl tanımın C dosyasına bırakılması gereklidir. Son olarak, nesne paradigmasında alıcı nesneyi temsilen tüm iletilere geçirilen saklı argüman (this veya self), derleyicinin nesne kavramından haberdar olmadığı düşünülerek, tüm fonksiyonlara ayrıca geçirilmelidir.

Gerçekleştirim kısmına geldiğimizde, nesne yönelimli dillerde derleyiciler tarafından yapılan bazı şeyleri programcının yapması gerektiği unutulmamalıdır. Örneğin, nesnenin özelliklerine göre sağlanan fonksiyon gerçekleştirimleri ile fonksiyon göstericileri ilklenmeli—yani, vtable programcı tarafından oluşturulmalı—yığın bellekten yer ayrımı işi yapıcı içinde yapılmalı ve nesnemiz ne kadar basit bir yapıya sahip olursa olsun yıkıcı görevini görecek bir fonksiyon yazılmalıdır.