Prosto i rzeczowo 🙂

Interface jest definicją(wzorem) dla klas, które będą go implementować.

W interfejsie określa się np. jakie metody mają być zdefiniowane w klasie. Klasa, która będzie dziedziczyć po interfejsie musi posiadać metody zdefiniowane w interfejsie.

Szybki przykład pokazujący o co chodzi w praktyce

public interface IBook
{
    public int GetPageCount();
    public string GetPrice();
}

public class Book : IBook
{
    public int GetPageCount()
    {
        return 300;
    }
    public string GetPrice()
    {
        return "30 złoty";
    }
}

Mamy interfejs IBook oraz klasę, która dziedziczy po interfejsie i musi posiadać metody, które zostały zdefiniowane w interfejsie zgodnie z wzorem.

Ważne

  • Interfejs w C# tworzymy używając słowa Interface
  • Dobrą praktyką jest pisać “I” na początku interfejsu, żeby w kodzie lepiej widoczne było, że jest to interface
  • Dziedziczenie po interface jest podobne jak w przypadku dziedziczenia po klasach i używamy “:” żeby podziedziczyć.
  • Super ważne: klasa może dziedziczyć tylko po jednej klasie (więcej tutaj), ale może dziedziczyć po wielu interfejsach
  • Do C# 8.0 metody w interfejsach nie mogą być implementowane, tzn. są tylko definicjami i nie mogą posiadać ciał. (są jak wzór pisma w urzędzie, który jest zalaminowany i wisi na ścianie ). Od C# 8.0 (wersja od sierpnia 2019) metody w interfejsach mogą być implementowane w prosty sposób. Są trochę jak wniosek, który można pobrać, i który ma już wypełnione np. dane kontaktowe i wymaga tylko podpisu (zostając w przykładach urzędowych :p )

Przykład interfejsu od wersji C# 8.0

public interface IFantasyBook
{
    public int GetPageCount();
    public string GetPrice();
    public string GetBookType()
    {
        return "Fantasy Book";
    }
}

public class HarryPotterSeriesBook : IFantasyBook
{
    public int GetPageCount()
    {
        return 300;
    }
    public string GetPrice()
    {
        return "30 złoty";
    }
}

public class TheLordOfTheRingsSerisesBook : IFantasyBook
{
    public int GetPageCount()
    {
        return 240;
    }
    public string GetPrice()
    {
        return "50 złoty";
    }
}

A tutaj przykład jak zrobić to samo przed wersją C# 8.0

public interface IFantasyBook
{
    public int GetPageCount();
    public string GetPrice();
    public string GetBookType();
}

public class HarryPotterSeriesBook : IFantasyBook
{
    public int GetPageCount()
    {
        return 300;
    }
    public string GetPrice()
    {
        return "30 złoty";
    }

    public string GetBookType()
    {
        return "Fantasy Book";
    }
}

public class TheLordOfTheRingsSerisesBook : IFantasyBook
{
    public int GetPageCount()
    {
        return 240;
    }
    public string GetPrice()
    {
        return "50 złoty";
    }
    public string GetBookType()
    {
        return "Fantasy Book";
    }
}

 Jak widać tutaj musieliśmy powtórzyć kod i w obu klasach zaimplementować metodę GetBookType tak samo, aby to obejść i nie powtarzać kodu trzeba wprowadzić jakąś klasę, po której będą dziedziczyć obie klasy.

public interface IFantasyBook
{
    public int GetPageCount();
    public string GetPrice();
    public string GetBookType();
}

public abstract class FantasyBook : IFantasyBook
{
    public abstract int GetPageCount();
    public abstract string GetPrice();
    public string GetBookType()
    {
        return "Fantasy Book";
    }
}

public class HarryPotterSeriesBook : FantasyBook, IFantasyBook
{
    public override int GetPageCount()
    {
        return 300;
    }

    public override string GetPrice()
    {
        return "30 złoty";
    }
}

public class TheLordOfTheRingsSerisesBook : FantasyBook, IFantasyBook
{
    public override int GetPageCount()
    {
        return 240;
    }

    public override string GetPrice()
    {
        return "50 złoty";
    }
}

Tutaj też trzeba dopisać trochę dodatkowego kodu, żeby nie powtarzać ciała metody GetBookType.

Jak widać implementowane interfejsy jest to ułatwienie w pewnych przypadkach, więc warto o tym pamiętać, że można implementować już interfejsy, ale nie trzeba. Jeżeli jest to coś z czym się źle czujesz, możesz dalej stosować interfejsy tylko jako wzory dla klas 🙂

Na koniec jeszcze ostatnia rada 🙂 Stosuj interfejsy! Mają one jedną mega ważna zaletę klasy, mogą dziedziczyć po więcej niż jednym interfejsie i dzięki interfejsom wymuszasz jak mają wyglądać klasy. To naprawdę bardzo przydatne w programowaniu.

Warto zrozumieć ten temat, bo to naprawdę ważne zagadnienie.