Menu
Coddy logo textTech

Arayüzleri Uygulama

Coddy'nin C Journey'sinin Object Oriented Programming bölümünün bir parçası — ders 41 / 61.

Artık bir interface'in ne olduğunu —yalnızca function pointers içeren bir struct— anladığınıza göre, bu sözleşmeyi yerine getiren concrete implementations oluşturmanın zamanı geldi.

Önceki dersteki ILogger arayüzünü hatırlayalım:

typedef void (*LogFunc)(const char* message);

typedef struct {
    LogFunc log;
} ILogger;

Bu arayüzü uygulamak için, LogFunc imzasıyla eşleşen gerçek fonksiyonlar yazarız, ardından bu fonksiyonların atandığı ILogger örnekleri oluştururuz:

void console_log(const char* message) {
    printf("[CONSOLE] %s\n", message);
}

void file_log(const char* message) {
    printf("[FILE] %s\n", message);  // Dosya çıktısı simüle ediliyor
}

ILogger create_console_logger() {
    ILogger logger = { console_log };
    return logger;
}

ILogger create_file_logger() {
    ILogger logger = { file_log };
    return logger;
}

Her bir "constructor" fonksiyonu, içine farklı bir fonksiyon bağlanmış bir ILogger döndürür. Bu logger'ları kullanan kodun, hangi uygulamayı (implementation) aldığını bilmesine gerek yoktur:

void do_work(ILogger* logger) {
    logger->log("Starting work...");
    logger->log("Work complete!");
}

int main() {
    ILogger console = create_console_logger();
    ILogger file = create_file_logger();
    
    do_work(&console);  // console_log kullanır
    do_work(&file);     // file_log kullanır
    return 0;
}

do_work fonksiyonu, günlükleme uygulamasından tamamen ayrılmıştır. Çekirdek mantığın hiçbirini değiştirmeden günlükleyicileri serbestçe değiştirebilirsiniz — bir arayüze göre programlamanın gücü budur.

challenge icon

Görev

Kolay

Farklı uygulamaların aynı arayüz sözleşmesini nasıl yerine getirebileceğini gösteren bir INotifier sistemi kuralım. Her ikisi de ortak bir arayüze uyan ancak farklı çıktılar üreten somut bildirimciler — bir EmailNotifier ve bir SMSNotifier — oluşturacaksınız.

Kodunuzu üç dosya halinde düzenleyeceksiniz:

  • notifier.h: Arayüzü burada tanımlayın. Bir const char* mesajı alan ve hiçbir şey döndürmeyen NotifyFunc adında bir fonksiyon göstericisi (function pointer) türü oluşturun. Ardından, yalnızca bu türde bir notify fonksiyon göstericisi içeren bir INotifier struct'ı tanımlayın. Ayrıca, her biri değer olarak bir INotifier döndüren iki yapıcı (constructor) fonksiyon bildirin: create_email_notifier ve create_sms_notifier.
  • notifier.c: Somut bildirim fonksiyonlarını ve yapıcıları burada uygulayın. Şunları oluşturun:
    • email_notify — mesajı şu formatta yazdırır: [EMAIL] message
    • sms_notify — mesajı şu formatta yazdırır: [SMS] message
    • create_email_notifieremail_notify fonksiyonuna bağlanmış bir INotifier döndürür
    • create_sms_notifiersms_notify fonksiyonuna bağlanmış bir INotifier döndürür
  • main.c: Her şeyi burada birleştirin. Bir bildirim türü ve bir mesaj okuyun, yapıcı fonksiyonları kullanarak uygun bildirimciyi oluşturun ve bildirimi arayüz üzerinden gönderin.

Programınız iki girdi alacaktır: bir bildirim türü (e-posta için 1, SMS için 2) ve gönderilecek bir mesaj.

Uygun bildirimciyi oluşturmak için yapıcı fonksiyonları kullanın, ardından mesajı görüntülemek için arayüz üzerinden notify fonksiyonunu çağırın.

Tür 1 ve mesaj Meeting at 3pm olduğunda örnek çıktı:

[EMAIL] Meeting at 3pm

Tür 2 ve mesaj Your code shipped olduğunda örnek çıktı:

[SMS] Your code shipped

Bu desenin gücü, main.c dosyasının her bir bildirimcinin dahili olarak nasıl çalıştığını bilmesine gerek duymamasıdır — sadece arayüzün notify fonksiyonunu çağırır ve doğru uygulama yürütülür. Başlık dosyanızda include guard kullanmayı unutmayın.

Kopya kağıdı

C'de bir arayüz (interface) uygulamak için, fonksiyon göstericisi imzasıyla eşleşen somut fonksiyonlar oluşturun ve ardından bunları arayüz örneklerine atayın.

Arayüzü fonksiyon göstericileri ile tanımlayın:

typedef void (*LogFunc)(const char* message);

typedef struct {
    LogFunc log;
} ILogger;

Somut uygulamaları oluşturun:

void console_log(const char* message) {
    printf("[CONSOLE] %s\n", message);
}

void file_log(const char* message) {
    printf("[FILE] %s\n", message);
}

Arayüz örnekleri oluşturmak için yapıcı (constructor) fonksiyonlar kullanın:

ILogger create_console_logger() {
    ILogger logger = { console_log };
    return logger;
}

ILogger create_file_logger() {
    ILogger logger = { file_log };
    return logger;
}

Arayüzü kullanan kod, belirli uygulamalardan bağımsızdır (decoupled):

void do_work(ILogger* logger) {
    logger->log("Starting work...");
}

int main() {
    ILogger console = create_console_logger();
    ILogger file = create_file_logger();
    
    do_work(&console);  // console_log kullanır
    do_work(&file);     // file_log kullanır
    return 0;
}

Kendin dene

#include <stdio.h>
#include "notifier.h"

int main() {
    int type;
    char message[256];
    
    // Bildirim türünü oku (e-posta için 1, SMS için 2)
    scanf("%d", &type);
    getchar(); // yeni satır karakterini tüket
    
    // Mesajı oku
    fgets(message, sizeof(message), stdin);
    // Varsa sondaki yeni satır karakterini kaldır
    int len = 0;
    while (message[len] != '\0') len++;
    if (len > 0 && message[len-1] == '\n') message[len-1] = '\0';
    
    // TODO: Türe göre uygun bildirimciyi oluştur
    // Tip 1 için create_email_notifier() kullanın
    // Tip 2 için create_sms_notifier() kullanın
    
    // TODO: Arayüz üzerinden bildirim fonksiyonunu çağırın
    // notifier.notify(message);
    
    return 0;
}
quiz iconKendini test et

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