Menu
Coddy logo textTech

Soyut Sınıflar

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

Bir soyut sınıf (abstract class), en az bir saf sanal fonksiyon (pure virtual function) içeren herhangi bir sınıftır. Eksik bir arayüze sahip olduğu için, bir soyut sınıftan doğrudan nesne oluşturamazsınız; bu sınıf yalnızca kendisinden miras alınması için mevcuttur.

class Shape {
public:
    virtual double area() = 0;      // Saf sanal - Shape'i soyut yapar
    virtual double perimeter() = 0; // Başka bir saf sanal fonksiyon
    
    void printInfo() {              // Normal metot - uygulaması var
        std::cout << "Area: " << area() << std::endl;
    }
    
    virtual ~Shape() = default;
};

Shape s;  // Hata: soyut sınıftan nesne oluşturulamaz

Soyut sınıflar; saf sanal fonksiyonların (uygulaması olmayan), normal sanal fonksiyonların (varsayılan uygulaması olan) ve sanal olmayan fonksiyonların bir karışımını içerebilir. Bu, türetilmiş sınıfların belirli işlevleri uygulamasını zorunlu kılarken, ortak davranışları tanımlamanıza olanak tanır.

class Circle : public Shape {
    double radius;
public:
    Circle(double r) : radius(r) {}
    
    double area() override { return 3.14159 * radius * radius; }
    double perimeter() override { return 2 * 3.14159 * radius; }
};

Circle c(5.0);      // Tamam: Circle tüm saf sanal fonksiyonları uygular
c.printInfo();      // Kalıtım alınan printInfo() fonksiyonunu kullanır, Circle'ın area() fonksiyonunu çağırır

Türetilmiş bir sınıf, somut (örneklenebilir) hale gelmek için tüm saf sanal fonksiyonları uygulamalıdır. Eğer herhangi birini uygulanmamış bırakırsa, kendisi de soyut kalmaya devam eder. Bu mekanizma, hiyerarşinizdeki her somut sınıfın gerekli işlevselliği sağlamasını garanti eder.

challenge icon

Görev

Kolay

Farklı medya türleri için soyut sınıfların nasıl sözleşmeler tanımladığını gösteren bir medya oynatıcı sistemi oluşturalım. Her medya oynatıcının ne yapması gerektiğini belirleyen soyut bir temel sınıf oluşturacak, ardından ses ve video içeriği için somut oynatıcılar uygulayacaksınız.

Kodunuzu üç dosya halinde düzenleyeceksiniz:

  • MediaPlayer.h: Tüm medya türleri için bir taslak görevi gören soyut bir MediaPlayer sınıfı tanımlayın. Soyut sınıfınız şunlara sahip olmalıdır:
    • Korumalı (protected) bir std::string title üyesi
    • Korumalı (protected) bir int duration üyesi (saniye cinsinden)
    • Her iki değeri de başlatan bir yapıcı (constructor)
    • Saf sanal (pure virtual) bir play() metodu — her medya türü farklı şekilde oynatılacaktır
    • std::string döndüren saf sanal (pure virtual) bir getMediaType() metodu
    • Şunu yazdıran normal (sanal olmayan) bir showInfo() metodu: <title> (<duration>s) - Type: <mediaType> — bu metod, türü almak için getMediaType() metodunu çağırmalıdır
    • Sanal bir yıkıcı (virtual destructor)
  • Players.h: MediaPlayer sınıfından miras alan iki somut medya oynatıcı uygulayın:

    AudioPlayer:

    • Özel (private) bir std::string artist üyesi
    • Başlık, süre ve sanatçı alan bir yapıcı
    • Şunu yazdırmak için play() metodunu uygulayın: Playing audio: <title> by <artist>
    • "Audio" döndürmek için getMediaType() metodunu uygulayın

    VideoPlayer:

    • Özel (private) bir std::string resolution üyesi
    • Başlık, süre ve çözünürlük alan bir yapıcı
    • Şunu yazdırmak için play() metodunu uygulayın: Playing video: <title> in <resolution>
    • "Video" döndürmek için getMediaType() metodunu uygulayın
  • main.cpp: Dört girdi okuyun (her biri ayrı bir satırda):
    1. Ses parçası başlığı
    2. Ses süresi (tam sayı)
    3. Video başlığı
    4. Video süresi (tam sayı)

    Sanatçısı "Unknown Artist" olan bir AudioPlayer ve çözünürlüğü "1080p" olan bir VideoPlayer oluşturun. Her ikisini de bir MediaPlayer* işaretçi dizisinde saklayın.

    Dizi boyunca döngü kurun ve her oynatıcı için önce showInfo(), ardından play() metodunu çağırın. Her medya öğesi arasına boş bir satır yazdırın. İşiniz bittiğinde dinamik olarak ayrılmış nesnelerinizi temizleyin.

Örneğin, Summer Vibes, 180, Nature Documentary ve 3600 girdileriyle:

Summer Vibes (180s) - Type: Audio
Playing audio: Summer Vibes by Unknown Artist

Nature Documentary (3600s) - Type: Video
Playing video: Nature Documentary in 1080p

showInfo() metodunun soyut temel sınıfta bir kez nasıl tanımlandığına ancak saf sanal getMediaType() metodunu nasıl çağırdığına dikkat edin — bu, soyut sınıfların somut uygulamaları, türetilmiş sınıfların sağlaması gereken metodlarla nasıl harmanlayabileceğini gösterir. Geçersiz kılınan (overridden) tüm metodlarda override anahtar kelimesini kullanmayı unutmayın.

Kopya kağıdı

Bir soyut sınıf (abstract class), en az bir saf sanal (pure virtual) fonksiyon içerir ve doğrudan örneklendirilemez. Kendisinden miras alınması ve türetilmiş sınıflar için bir arayüz tanımlaması amacıyla vardır.

Bir Soyut Sınıf Tanımlama

Saf sanal bir fonksiyon bildirmek için = 0 kullanın:

class Shape {
public:
    virtual double area() = 0;      // Saf sanal fonksiyon
    virtual double perimeter() = 0; // Shape'i soyut yapar
    
    void printInfo() {              // Uygulaması olan normal metot
        std::cout << "Area: " << area() << std::endl;
    }
    
    virtual ~Shape() = default;     // Sanal yıkıcı
};

Soyut sınıflar şunları içerebilir:

  • Saf sanal fonksiyonlar (uygulama içermez)
  • Normal sanal fonksiyonlar (varsayılan uygulama ile)
  • Sanal olmayan fonksiyonlar

Somut Sınıfları Uygulama

Türetilmiş bir sınıfın örneklendirilebilir hale gelmesi için tüm saf sanal fonksiyonları uygulaması gerekir:

class Circle : public Shape {
    double radius;
public:
    Circle(double r) : radius(r) {}
    
    double area() override { return 3.14159 * radius * radius; }
    double perimeter() override { return 2 * 3.14159 * radius; }
};

Circle c(5.0);      // Tamam: tüm saf sanal fonksiyonlar uygulandı
c.printInfo();      // Miras alınan metot Circle'ın area() fonksiyonunu çağırır

Eğer türetilmiş bir sınıf tüm saf sanal fonksiyonları uygulamazsa, soyut kalmaya devam eder ve örneklendirilemez.

Kendin dene

#include <iostream>
#include <string>
#include "MediaPlayer.h"
#include "Players.h"

int main() {
    // Girdileri oku
    std::string audioTitle;
    int audioDuration;
    std::string videoTitle;
    int videoDuration;
    
    std::getline(std::cin, audioTitle);
    std::cin >> audioDuration;
    std::cin.ignore();
    std::getline(std::cin, videoTitle);
    std::cin >> videoDuration;
    
    // TODO: Sanatçısı "Unknown Artist" olan bir AudioPlayer oluşturun
    
    // TODO: Çözünürlüğü "1080p" olan bir VideoPlayer oluşturun
    
    // TODO: Her ikisini de bir MediaPlayer* işaretçi dizisinde saklayın
    
    // TODO: Dizi boyunca döngü kurun ve her oynatıcı için:
    //       1. showInfo() fonksiyonunu çağırın
    //       2. play() fonksiyonunu çağırın
    //       3. Her medya öğesi arasına boş bir satır yazdırın
    
    // TODO: Dinamik olarak ayrılmış nesneleri temizleyin
    
    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