Menu
Coddy logo textTech

C++'ta Arayüz Tasarımı

Coddy'nin C++ Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 61 / 104.

C++'ta bir arayüz, (sanal) yıkıcı dışındaki her üye işlevin saf sanal olduğu soyut bir sınıftır. Bazı uygulamalar içerebilen soyut sınıfların aksine, arayüzler yalnızca hangi işlemlerin var olması gerektiğini tanımlar; herhangi bir davranış içermeden bir sözleşme belirtir.

class Drawable {
public:
    virtual void draw() = 0;
    virtual void resize(double factor) = 0;
    virtual ~Drawable() = default;
};

Bu Drawable arayüzü, onu uygulayan herhangi bir sınıfın draw() ve resize() yöntemlerine sahip olacağını garanti eder, ancak bunların nasıl çalıştığı hakkında hiçbir şey söylemez. Bu ayrım güçlüdür - kod, somut türler hakkında hiçbir şey bilmeden arayüze bağımlı olabilir.

class Circle : public Drawable {
    double radius;
public:
    Circle(double r) : radius(r) {}
    void draw() override { std::cout << "Drawing circle" << std::endl; }
    void resize(double factor) override { radius *= factor; }
};

class Button : public Drawable {
    std::string label;
public:
    Button(std::string l) : label(l) {}
    void draw() override { std::cout << "Drawing button: " << label << std::endl; }
    void resize(double factor) override { /* butonu yeniden boyutlandır */ }
};

Bir sınıf birden fazla arayüzü uygulayabilir; bu, nesnelerin farklı rolleri yerine getirebildiği esnek tasarımlar sağlar:

class Clickable {
public:
    virtual void onClick() = 0;
    virtual ~Clickable() = default;
};

class IconButton : public Drawable, public Clickable {
public:
    void draw() override { std::cout << "Drawing icon" << std::endl; }
    void resize(double factor) override { }
    void onClick() override { std::cout << "Clicked!" << std::endl; }
};

Arayüzler gevşek bağlılığı teşvik eder - kodunuz somut uygulamalar yerine soyutlamalara bağlıdır; bu da kodu genişletmeyi ve test etmeyi kolaylaştırır.

challenge icon

Görev

Kolay

Farklı cihaz türleri için arayüzlerin sözleşmeleri nasıl tanımladığını gösteren bir cihaz yönetim sistemi oluşturalım. Cihazların uygulayabileceği iki ayrı arayüz oluşturacak, ardından bu sözleşmelerden birini veya her ikisini yerine getiren somut cihaz sınıfları oluşturacaksın.

Kodunu üç dosyaya ayıracaksın:

  • Interfaces.h: Farklı cihaz yeteneklerini temsil eden iki saf soyut sınıf (arayüz) tanımla:

    Powerable: açılıp kapatılabilen herhangi bir cihaz:

    • Saf sanal bir powerOn() metodu
    • Saf sanal bir powerOff() metodu
    • getPowerStatus() döndüren saf sanal bir std::string metodu
    • Sanal bir yıkıcı

    Connectable: bir ağa bağlanabilen herhangi bir cihaz:

    • Saf sanal bir connect(const std::string& network) metodu
    • Saf sanal bir disconnect() metodu
    • getConnectionInfo() döndüren saf sanal bir std::string metodu
    • Sanal bir yıkıcı
  • Devices.h: Bu arayüzleri kullanan somut cihaz sınıflarını uygula:

    Lamp: yalnızca Powerable arayüzünü uygular:

    • Özel bir bool isOn üyesi (başlangıç değeri false)
    • Özel bir std::string name üyesi
    • Lambanın adını alan bir kurucu
    • powerOn(), isOn değerini true olarak ayarlar ve şunu yazdırır: <name>: Light turned on
    • powerOff(), isOn değerini false olarak ayarlar ve şunu yazdırır: <name>: Light turned off
    • getPowerStatus(), duruma bağlı olarak "ON" veya "OFF" döndürür

    SmartTV: hem Powerable hem de Connectable arayüzlerini uygular:

    • Özel üyeler: bool isOn (başlangıç değeri false), std::string brand, std::string currentNetwork (başlangıç değeri boş)
    • TV'nin markasını alan bir kurucu
    • powerOn(), isOn değerini true olarak ayarlar ve şunu yazdırır: <brand> TV: Powered on
    • powerOff(), isOn değerini false olarak ayarlar, ağı temizler ve şunu yazdırır: <brand> TV: Powered off
    • getPowerStatus(), "ON" veya "OFF" döndürür
    • connect(), ağ adını kaydeder ve şunu yazdırır: <brand> TV: Connected to <network>
    • disconnect(), ağı temizler ve şunu yazdırır: <brand> TV: Disconnected
    • getConnectionInfo(), bağlıysa "Connected to <network>", boşsa "Not connected" döndürür
  • main.cpp: Üç girdi oku (her biri ayrı bir satırda):
    1. Lamba adı
    2. TV markası
    3. Ağ adı

    Bir Lamp ve bir SmartTV oluştur. Aynı arayüzün farklı cihazlarla nasıl kullanılabileceğini göster:

    İlk olarak her iki cihazla Powerable arayüzü üzerinden çalış. Her ikisine işaretçileri bir Powerable* dizisinde sakla, ardından dizi üzerinde döngü kurarak her biri için powerOn() çağır ve durumlarını şu şekilde yazdır: Status: <powerStatus>

    Boş bir satır yazdır, ardından Connectable arayüzü üzerinden SmartTV ile çalış. SmartTV'nize bir Connectable* işaretçisi oluştur, ağ adıyla connect() çağır ve şunu yazdır: Connection: <connectionInfo>

    Bir boş satır daha yazdır, ardından Powerable dizisi üzerinden her iki cihazı kapat ve son durumlarını göster.

Örneğin girdiler Desk Lamp, Samsung ve HomeWiFi olduğunda:

Desk Lamp: Light turned on
Status: ON
Samsung TV: Powered on
Status: ON

Samsung TV: Connected to HomeWiFi
Connection: Connected to HomeWiFi

Desk Lamp: Light turned off
Status: OFF
Samsung TV: Powered off
Status: OFF

SmartTV'nin, hangi arayüz işaretçisini kullandığına bağlı olarak Powerable veya Connectable olarak ele alınabildiğine dikkat et. Bu esneklik, birden fazla arayüz uygulamanın gücüdür. Kodun, somut türü bilmeden, ihtiyaç duyduğu sözleşmeyi yerine getiren herhangi bir cihazla çalışabilir.

Kendin dene

#include <iostream>
#include <string>
#include "Devices.h"

using namespace std;

int main() {
    // Girdileri oku
    string lampName;
    string tvBrand;
    string networkName;
    
    getline(cin, lampName);
    getline(cin, tvBrand);
    getline(cin, networkName);
    
    // TODO: Bir Lamp ve bir SmartTV nesnesi oluştur
    
    // TODO: Her iki cihazı içeren Powerable* işaretçilerinden bir dizi oluştur
    
    // TODO: Diziyi döngüyle gez ve her cihazda powerOn() çağır
    // Her powerOn() sonrasında yazdır: Status: <powerStatus>
    
    // TODO: Boş bir satır yazdır
    
    // TODO: SmartTV için bir Connectable* işaretçisi oluştur
    // Ağ adıyla connect() çağır
    // Print: Connection: <connectionInfo>
    
    // TODO: Boş bir satır yazdır
    
    // TODO: Powerable dizisini döngüyle gez ve her cihazda powerOff() çağır
    // Her powerOff() sonrasında yazdır: Status: <powerStatus>
    
    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.

Nesne Yönelimli Programlama bölümündeki tüm dersler

Kendi başına pratik yap: Online C++ derleyicisi