Interfejsy w C#

Interfejsy w C# to specjalne typy, które deklarują zestaw metod, właściwości, zdarzeń lub indeksatorów, ale nie zawierają ich implementacji. Służą one jako kontrakt, który klasy lub struktury mogą implementować. Dzięki interfejsom możemy definiować zachowanie bez określania, jak dokładnie ma być ono zaimplementowane.

Dlaczego warto używać interfejsów?

Polimorfizm: Umożliwiają tworzenie kodu, który może działać na różnych typach obiektów w jednolity sposób.

Abstrakcja: Pozwalają skupić się na tym, co obiekt robi, a nie jak to robi.

Elastyczność: Ułatwiają modyfikację i rozszerzanie kodu bez naruszania istniejącej struktury.

Definiowanie interfejsu

Aby zdefiniować interfejs, używamy słowa kluczowego interface. Interfejsy zazwyczaj nazywamy, poprzedzając nazwę literą I (np. IObliczenia).

public interface IZwierze
{
    void Jedz();
    void Spij();
}

Implementacja interfejsu w klasie

Klasa, która implementuje interfejs, musi zdefiniować wszystkie jego człony.

public class Kot : IZwierze
{
    public void Jedz()
    {
        Console.WriteLine("Kot je.");
    }

    public void Spij()
    {
        Console.WriteLine("Kot śpi.");
    }

    public void Mialcz()
    {
        Console.WriteLine("Kot miauczy.");
    }
}


Przykład użycia

IZwierze zwierze = new Kot();
zwierze.Jedz(); // Wyświetli: Kot je.
zwierze.Spij(); // Wyświetli: Kot śpi.

Implementacja wielu interfejsów

Klasa może implementować wiele interfejsów.

public interface ISsak
{
    void KarmMlekiem();
}

public class Pies : IZwierze, ISsak
{
    public void Jedz()
    {
        Console.WriteLine("Pies je.");
    }

    public void Spij()
    {
        Console.WriteLine("Pies śpi.");
    }

    public void KarmMlekiem()
    {
        Console.WriteLine("Pies karmi młode mlekiem.");
    }
}

Polimorfizm z interfejsami

Interfejsy pozwalają na traktowanie różnych obiektów w ten sam sposób.

List<IZwierze> zwierzeta = new List<IZwierze>();
zwierzeta.Add(new Kot());
zwierzeta.Add(new Pies());

foreach (var z in zwierzeta)
{
    z.Jedz();
    z.Spij();
}

Interfejsy a klasy abstrakcyjne

Interfejsy: Nie zawierają implementacji metod (do C# 8.0), klasy mogą implementować wiele interfejsów.

Klasy abstrakcyjne: Mogą zawierać implementacje, klasa może dziedziczyć tylko jedną klasę (abstrakcyjną lub nie).

Domyślne implementacje w interfejsach (C# 8.0 i nowsze)

Od wersji C# 8.0 możliwe jest dodawanie domyślnych implementacji metod w interfejsach.

public interface IKształt
{
    double ObliczPole();

    double ObliczObwód()
    {
        return 0; // Domyślna implementacja
    }
}

Praktyczne zastosowanie

Interfejsy są często używane w dużych projektach do:

• Definiowania API między różnymi modułami.

• Tworzenia łatwo testowalnego kodu (np. poprzez wstrzykiwanie zależności).

• Implementacji wzorców projektowych (np. strategia, obserwator).

Ćwiczenie

Stwórz interfejs IPojazd z metodami Jedz() i Zatrzymaj(). Następnie zaimplementuj go w klasach Samochod i Rower, definiując odpowiednie zachowania dla tych metod.


Przykładowe rozwiązanie

public interface IPojazd
{
    void Jedz();
    void Zatrzymaj();
}

public class Samochod : IPojazd
{
    public void Jedz()
    {
        Console.WriteLine("Samochód jedzie.");
    }

    public void Zatrzymaj()
    {
        Console.WriteLine("Samochód się zatrzymuje.");
    }
}

public class Rower : IPojazd
{
    public void Jedz()
    {
        Console.WriteLine("Rower jedzie.");
    }

    public void Zatrzymaj()
    {
        Console.WriteLine("Rower się zatrzymuje.");
    }
}

Zapamiętaj:

• Interfejsy definiują co klasa ma robić, nie jak.

• Klasa może implementować wiele interfejsów.

• Używaj interfejsów do definiowania kontraktów między różnymi częściami aplikacji.