Menu
CoddyTech

Arayüz vs Soyut Sınıf

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

Hem arayüzler hem de soyut sınıflar, diğer sınıfların uyması gereken sözleşmeleri tanımlamanı sağlar; ancak farklı amaçlara hizmet eder ve farklı özelliklere sahiptir.

Bir arayüz, herhangi bir uygulama ayrıntısı içermeden bir sınıfın ne yapması gerektiğini tanımlar. Bu, saf bir sözleşmedir:

public interface IFlyable
{
    void Fly();
}

public class Bird : IFlyable
{
    public void Fly()
    {
        Console.WriteLine("Flapping wings");
    }
}

Soyut sınıf hem bir sözleşme hem de paylaşılan bir uygulama sağlayabilir. Kısmi bir taslaktır:

public abstract class Vehicle
{
    public string Brand { get; set; }
    
    public void StartEngine()
    {
        Console.WriteLine("Engine started");
    }
    
    public abstract void Drive();  // Uygulanmalıdır
}

public class Car : Vehicle
{
    public override void Drive()
    {
        Console.WriteLine("Driving on roads");
    }
}

Temel farklılıklar kalıtım kuralları ve kullanım amacıyla ilgilidir.

Bir sınıf birden fazla arayüzü uygulayabilir, ancak yalnızca bir soyut sınıftan kalıtım alabilir.

Bir sınıf aynı zamanda bir soyut sınıftan kalıtım alabilir ve arayüzleri uygulayabilir: iki nokta üst üste işaretinden sonra önce temel sınıf, ardından virgüllerle ayrılmış arayüzler gelir:

public class Airplane : Vehicle, IFlyable
{
    public override void Drive()
    {
        Console.WriteLine("Taxiing to the runway");
    }

    public void Fly()
    {
        Console.WriteLine("Flying above the clouds");
    }
}

İlgisiz sınıfların davranış paylaşması gerektiğinde bir arayüz kullan (kuşlar ve uçaklar için IFlyable gibi). İlişkili sınıflar ortak kod ve durumu paylaştığında bir soyut sınıf kullan (araçların ortak bir motor çalıştırma mekanizmasını paylaşması gibi).

Abstract sınıfların üyelerinde yapıcılar, alanlar ve erişim belirleyicileri bulunabilir. Arayüzlerde geleneksel olarak bunlar bulunamazdı, ancak modern C# varsayılan uygulamalara izin verir.

Şüpheye düştüğünde esneklik için arayüzleri tercih et; ortak bir uygulama gerekli hâle gelirse daha sonra her zaman soyut bir sınıf ekleyebilirsin.

challenge icon

Görev

Kolay

Bir arayüzün mü yoksa soyut sınıfın mı kullanılacağını gösteren bir medya oynatıcı sistemi oluşturalım. İlişkisiz cihazların oynatma davranışını bir arayüz aracılığıyla paylaştığı, ilişkili medya türlerinin ise ortak uygulamayı bir soyut sınıf aracılığıyla paylaştığı bir tasarım oluşturacaksın.

Kodunu dört dosyaya ayıracaksın:

  • IPlayable.cs: Media ad alanında IPlayable adlı bir arayüz tanımla. Bu arayüz, ister telefon, ister TV, ister özel bir müzik çalar olsun, medya oynatabilen her şey için sözleşmeyi temsil eder. Bir string döndüren tek bir Play() metodu bildirmelidir.
  • MediaFile.cs: Media ad alanında MediaFile adlı soyut bir sınıf tanımla. Bu sınıf, tüm medya dosakları için ortak temeli temsil eder. Bir Title özelliği (string) ve bir Duration özelliği (saniyeyi temsil eden int) olmalıdır. Her iki değeri de ayarlayan bir kurucu ekle. "{Title} ({Duration}s)" döndüren GetInfo() adlı somut bir metot ekle. Ayrıca string döndüren GetType() adlı soyut bir metot bildir; her medya türü ne tür bir dosya olduğunu tanımlayacaktır.
  • AudioFile.cs: Media ad alanında, MediaFile sınıfından kalıtım alan ve IPlayable arayüzünü uygulayan bir AudioFile sınıfı tanımla. Bir Artist özelliği (string) ekle. Kurucu title, duration ve artist değerlerini kabul etmelidir. GetType() metodunu, "Audio" döndürecek şekilde geçersiz kıl. Play() metodunu, "Playing audio: {Title} by {Artist}" döndürecek şekilde uygula.
  • Program.cs: Ana dosyanda, girdi değerlerini kullanarak bir AudioFile oluştur. Sınıfın her iki yönünü de göster: GetInfo() ve GetType() metotlarını çağır (soyut sınıftan kalıtılan), ardından Play() metodunu çağır (arayüzden). Ses dosyasını bir IPlayable değişkeninde sakla ve arayüz çok biçimliliğini göstermek için Play() metodunu tekrar çağır.

Üç girdi alacaksın:

  • Şarkı adı
  • Saniye cinsinden süre
  • Sanatçı adı

Çıktıyı şu biçimde yazdır:

Info: {GetInfo() result}
Type: {GetType() result}
Direct: {Play() result}
Via Interface: {Play() result from IPlayable variable}

Örneğin, girdiler Bohemian Rhapsody, 354 ve Queen ise çıktı şöyle olmalıdır:

Info: Bohemian Rhapsody (354s)
Type: Audio
Direct: Playing audio: Bohemian Rhapsody by Queen
Via Interface: Playing audio: Bohemian Rhapsody by Queen

AudioFile sınıfının her iki yaklaşımdan da nasıl yararlandığına dikkat et: soyut sınıftan ortak uygulamayı (GetInfo()) devralırken IPlayable sözleşmesini de yerine getirir. Soyut sınıf, ilişkili medya türleri için kodun yeniden kullanılmasını sağlarken arayüz, herhangi bir ilişkisiz sınıfın kalıtım hiyerarşisini paylaşmadan "oynatılabilir" olmasına olanak tanır.

Kendin dene

using System;
using Media;

class Program
{
    public static void Main(string[] args)
    {
        // Giriş değerlerini oku
        string title = Console.ReadLine();
        int duration = Convert.ToInt32(Console.ReadLine());
        string artist = Console.ReadLine();
        
        // TODO: Giriş değerlerini kullanarak bir AudioFile oluştur
        
        // TODO: Info: yazdır, ardından GetInfo() sonucunu yazdır
        
        // TODO: Type: yazdır, ardından GetType() sonucunu yazdır
        
        // TODO: Direct: yazdır, ardından Play() sonucunu yazdır
        
        // TODO: Ses dosyasını bir IPlayable değişkeninde sakla
        
        // TODO: Via Interface: yazdır, ardından IPlayable değişkeninden Play() sonucunu yazdır
    }
}
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