Menu
Coddy logo textTech

Belirgin Arayüzler

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

Bir sınıf, aynı isme sahip üyelere sahip birden fazla arayüzü uyguladığında, bir isim çakışmasıyla karşılaşırsınız. Açık arayüz uygulaması (explicit interface implementation), her bir arayüz için ayrı uygulamalar sağlamanıza olanak tanıyarak bu sorunu çözer.

Açık uygulama (explicit implementation) ile, üye adının önüne arayüz adını getirirsiniz ve erişim belirleyicisini atlarsınız:

public interface IAmericanPlug
{
    void Connect();
}

public interface IEuropeanPlug
{
    void Connect();
}

public class UniversalAdapter : IAmericanPlug, IEuropeanPlug
{
    void IAmericanPlug.Connect()
    {
        Console.WriteLine("Connected to 120V");
    }
    
    void IEuropeanPlug.Connect()
    {
        Console.WriteLine("Connected to 220V");
    }
}

Açıkça uygulanan üyelere yalnızca arayüz türündeki bir değişken aracılığıyla erişilebilir, sınıfın kendisi üzerinden erişilemez:

var adapter = new UniversalAdapter();
// adapter.Connect();  // Derlenmeyecek!

IAmericanPlug american = adapter;
american.Connect();  // 120V'a bağlandı

IEuropeanPlug european = adapter;
european.Connect();  // 220V'a bağlandı

Bu teknik, arayüz üyelerini sınıfın genel API'sinden gizlemek istediğinizde de yararlıdır. Bir yöntem yalnızca nesneye belirli bir arayüz olarak yaklaşıldığında anlamlıysa, açık uygulama (explicit implementation) sözleşmeyi yerine getirirken sınıfınızın yüzey alanını temiz tutar.

challenge icon

Görev

Kolay

Açık arabirim uygulamasının (explicit interface implementation), tek bir sınıfın hangi arabirimin kullanıldığına bağlı olarak nasıl farklı davranışlar sergilemesine izin verdiğini gösteren bir rapor oluşturucu sistemi kuralım. Ekran görüntüsü ve yazdırma için farklı şekilde biçimlendirilebilen bir belge oluşturacaksınız.

Kodunuzu dört dosya halinde düzenleyeceksiniz:

  • IDisplayable.cs: Reports ad alanı (namespace) içinde IDisplayable adında bir arabirim tanımlayın. Bu arabirim, ekranda gösterilebilen içeriği temsil eder. Geriye bir dize (string) döndüren Render() adında bir metot bildirmelidir.
  • IPrintable.cs: Reports ad alanı içinde IPrintable adında bir arabirim tanımlayın. Bu arabirim, bir yazıcıya gönderilebilen içeriği temsil eder. Bu da geriye bir dize döndüren Render() adında bir metot bildirmelidir - bunun IDisplayable ile bir isim çakışması yarattığına dikkat edin!
  • Report.cs: Reports ad alanı içinde hem IDisplayable hem de IPrintable arabirimlerini uygulayan bir Report sınıfı tanımlayın. Raporun bir Title özelliği (string) ve bir Content özelliği (string) olmalı ve her iki değeri de ayarlayan bir yapıcı metodu (constructor) bulunmalıdır. Farklı Render() davranışları sağlamak için açık arabirim uygulamasını kullanın:
    • Ekran için işlendiğinde: "[SCREEN] {Title}: {Content}"
    • Yazdırma için işlendiğinde: "[PRINT] {Title} | {Content}"
  • Program.cs: Ana dosyanızda, girdi değerlerini kullanarak bir Report nesnesi oluşturun. Açık uygulamalara yalnızca arabirim değişkenleri aracılığıyla erişilebildiğinden, aynı raporu hem bir IDisplayable değişkeninde hem de bir IPrintable değişkeninde saklayın, ardından aynı nesnenin hangi arabirimi kullandığınıza bağlı olarak nasıl farklı çıktılar ürettiğini göstermek için her birinde Render() metodunu çağırın.

İki girdi alacaksınız:

  • Rapor başlığı
  • Rapor içeriği

Çıktıyı şu formatta yazdırın:

Display version:
{Render() via IDisplayable}
Print version:
{Render() via IPrintable}

Örneğin, girdiler Sales Report ve Q4 revenue increased by 15% ise, çıktı şöyle olmalıdır:

Display version:
[SCREEN] Sales Report: Q4 revenue increased by 15%
Print version:
[PRINT] Sales Report | Q4 revenue increased by 15%

Aynı Report nesnesinin, ona erişmek için hangi arabirim referansını kullandığınıza bağlı olarak nasıl farklı davrandığına dikkat edin. Bu, açık arabirim uygulamasının gücüdür - bağlama uygun davranış sağlarken isim çakışmalarını çözer!

Kopya kağıdı

Bir sınıf, aynı ada sahip üyelere sahip birden fazla arayüzü (interface) uyguladığında, her bir arayüz için ayrı uygulamalar sağlamak amacıyla açık arayüz uygulaması (explicit interface implementation) kullanabilirsiniz.

Bir arayüz üyesini açıkça uygulamak için, üye adının önüne arayüz adını ekleyin ve erişim belirleyicisini (access modifier) kaldırın:

public interface IAmericanPlug
{
    void Connect();
}

public interface IEuropeanPlug
{
    void Connect();
}

public class UniversalAdapter : IAmericanPlug, IEuropeanPlug
{
    void IAmericanPlug.Connect()
    {
        Console.WriteLine("Connected to 120V");
    }
    
    void IEuropeanPlug.Connect()
    {
        Console.WriteLine("Connected to 220V");
    }
}

Açıkça uygulanan üyelere yalnızca arayüz türündeki bir değişken aracılığıyla erişilebilir, sınıfın kendisi üzerinden erişilemez:

var adapter = new UniversalAdapter();
// adapter.Connect();  // Derlenmeyecektir!

IAmericanPlug american = adapter;
american.Connect();  // Connected to 120V

IEuropeanPlug european = adapter;
european.Connect();  // Connected to 220V

Bu teknik şunlar için kullanışlıdır:

  • Arayüz üyeleri arasındaki ad çakışmalarını çözmek
  • Arayüz üyelerini, yalnızca belirli bir arayüz bağlamında anlamlı olduklarında sınıfın genel API'sinden gizlemek

Kendin dene

using System;
using Reports;

class Program
{
    public static void Main(string[] args)
    {
        // Girdiyi oku
        string title = Console.ReadLine();
        string content = Console.ReadLine();

        // TODO: title ve content ile bir Report nesnesi oluşturun

        // TODO: Raporu bir IDisplayable değişkeninde saklayın

        // TODO: Aynı raporu bir IPrintable değişkeninde saklayın

        // TODO: IDisplayable üzerinde Render() metodunu çağırarak ekran sürümünü yazdırın
        Console.WriteLine("Display version:");
        // Render sonucunu buraya yazdırın

        // TODO: IPrintable üzerinde Render() metodunu çağırarak yazdırma sürümünü yazdırın
        Console.WriteLine("Print version:");
        // Render sonucunu buraya yazdırın
    }
}
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