Arayüz Kavramı
Coddy'nin C Journey'sinin Object Oriented Programming bölümünün bir parçası — ders 40 / 61.
Şu ana kadar struct'larımız veriyi ve davranışı bir arada sundu — örneğin, bir fonksiyon işaretçisinin yanındaki bir isim gibi. Peki ya bir struct sadece fonksiyon işaretçileri içerseydi? Bu, güçlü bir şey ortaya çıkarır: bir arayüz (interface).
Bir arayüz (interface), işlemlerin nasıl çalıştığını belirtmeden hangi işlemlerin mevcut olduğunu tanımlar. Bu, "bu arayüzü uygulayan herhangi bir nesne bu fonksiyonları sağlamalıdır" diyen bir sözleşmedir.
typedef void (*LogFunc)(const char* message);
typedef struct {
LogFunc log;
} ILogger;ILogger yapısı bir fonksiyon göstericisinden başka bir şey içermez. Kendine ait hiçbir verisi yoktur — tamamen davranışı tanımlar. "I" öneki, bunun bir arayüz olduğunu belirten yaygın bir kuraldır.
Bir ILogger kabul eden herhangi bir kod, günlük mesajının nereye gittiğiyle ilgilenmez. Konsola yazdırabilir, bir dosyaya yazabilir veya bir ağ üzerinden veri gönderebilir. Arayan kişi sadece log fonksiyonunu çağırabileceğini bilir:
void process(ILogger* logger, const char* msg) {
logger->log(msg); // Nasıl logladığını bilmiyoruz
}Bu ayrım, polimorfizmin özüdür. process fonksiyonu herhangi bir logger uygulamasıyla çalışır — fonksiyonun kodunu değiştirmeden davranışları değiştirebilirsiniz. Bir sonraki derste, bu arayüz sözleşmesini yerine getiren somut uygulamalar oluşturacaksınız.
Görev
KolayHerhangi bir hesap makinesinin nasıl çalıştığını belirtmeden hangi işlemleri desteklemesi gerektiğini tanımlayan, yalnızca fonksiyon göstericileri (function pointers) içeren bir yapı olan ICalculator arayüzünü oluşturalım.
Kodunuzu düzenlemek için iki dosya oluşturacaksınız:
calculator.h: Arayüzünüzü burada tanımlayın. İkiintparametresi alan ve birintdöndürenBinaryOpadında bir fonksiyon göstericisi türü oluşturun. Ardından, yalnızca iki fonksiyon göstericisi içeren birICalculatoryapısı (struct) tanımlayın:operate(BinaryOptüründe) vedescribe(hiçbir parametre almayan ve hiçbir şey döndürmeyen bir fonksiyon göstericisi). Bu yapı tamamen bir arayüzdür; veri tutmaz, sadece davranış tutar.main.c: Başlık dosyanızı dahil edin ve arayüzü karşılayabilecek somut fonksiyonları uygulayın:add— iki tam sayının toplamını döndürürmultiply— iki tam sayının çarpımını döndürürdescribe_add—Additionyazdırırdescribe_multiply—Multiplicationyazdırır
ICalculatorörneği oluşturun, girişe göre yapılandırın ve bir hesaplama yapmak için kullanın.
Programınız üç giriş alacaktır: iki tam sayı ve bir işlem kodu (toplama için 1, çarpma için 2).
İşlem koduna bağlı olarak, ICalculator yapınızı uygun fonksiyon çiftiyle bağlayın. Ardından, işlem adını yazdırmak için arayüz üzerinden describe fonksiyonunu çağırın ve sonrasında sonucu hesaplayıp yazdırmak için operate fonksiyonunu çağırın.
Girişler 5, 3 ve 1 olduğunda örnek çıktı:
Addition
8Girişler 4, 7 ve 2 olduğunda örnek çıktı:
Multiplication
28Buradaki temel fikir, ICalculator yapınızın bir sözleşme tanımlamasıdır; onu kullanan herhangi bir kod, hangi özel fonksiyonların bağlı olduğunu bilmeden describe ve operate fonksiyonlarını çağırabileceğini bilir. Başlık dosyanızda "include guard" kullanmayı unutmayın.
Kopya kağıdı
Bir arayüz (interface), yalnızca fonksiyon göstericileri içeren ve işlemlerin nasıl çalıştığını belirtmeden hangi işlemlerin mevcut olduğunu tanımlayan bir yapıdır (struct).
Bir arayüz tanımlama:
typedef void (*LogFunc)(const char* message);
typedef struct {
LogFunc log;
} ILogger;"I" öneki, bunun bir arayüz olduğunu belirten yaygın bir kuraldır. Yapı (struct) hiçbir veri içermez; tamamen davranışı tanımlar.
Bir arayüzü kullanma:
void process(ILogger* logger, const char* msg) {
logger->log(msg); // Nasıl log tuttuğunu bilmiyoruz
}Bu ayrım çok biçimliliği (polymorphism) sağlar; fonksiyon, arayüzün herhangi bir uygulamasıyla çalışır ve fonksiyonun kodunu değiştirmeden davranışları değiştirmenize olanak tanır.
Kendin dene
#include <stdio.h>
#include "calculator.h"
// TODO: Toplama fonksiyonunu uygula
// İki tam sayının toplamını döndürür
// TODO: Çarpma fonksiyonunu uygula
// İki tam sayının çarpımını döndürür
// TODO: describe_add fonksiyonunu uygula
// "Addition" yazdırır
// TODO: describe_multiply fonksiyonunu uygula
// "Multiplication" yazdırır
int main() {
int num1, num2, op_code;
scanf("%d", &num1);
scanf("%d", &num2);
scanf("%d", &op_code);
// TODO: Bir ICalculator örneği oluştur
// TODO: op_code'a göre (toplama için 1, çarpma için 2),
// hesap makinesini uygun fonksiyonlarla bağla
// TODO: Arayüz üzerinden describe fonksiyonunu çağır
// TODO: Arayüz üzerinden operate fonksiyonunu çağır ve sonucu yazdır
return 0;
}
Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Object Oriented Programming bölümündeki tüm dersler
1Modüler Programlama Temelleri
Başlık DosyalarıInclude Guard'larKaynak DosyalarıStatik FonksiyonlarÖzet: Modüler Hesap Makinesi4Kapsülleme
Opaque Pointer KavramıOpaque Struct TanımlamaGetter ve Setter MetotlarıSetter Metotlarında DoğrulamaÖzet: Gizli Kutu2Nesneler ve Metotlar
Nesne Olarak Struct'lar'Self' İşaretçisiConst Doğruluğuİşaretçi vs DeğerYardımcı MetotlarÖzet: Point Manager5Proje: Basit Banka Hesabı
Proje KurulumuHesabın Oluşturulması3Nesne Yaşam Döngüsü
Constructor DeseniDestructor DeseniStack İlklendirmeDerin KopyalamaÖzet: String Wrapper6Kompozisyon Yoluyla Kalıtım
Struct Gömmeİlk Üye KuralıÜst Üyelere ErişimUpcastingÖzet: Şekil Hiyerarşisi