Sobes.tech
Middle

Po co są interfejsy, jeśli istnieją już klasy abstrakcyjne?

sobes.tech AI

Odpowiedź od AI

  1. Wielodziedziczenie. Klasa może implementować wiele interfejsów, ale dziedziczyć tylko z jednej klasy (w tym abstrakcyjnej).
    interface IDrivable {}
    interface IFlyable {}
    
    class Car : IDrivable {} // Dziedziczy tylko z jednej klasy (object domyślnie)
    
    class FlyingCar : IDrivable, IFlyable {} // Implementuje wiele interfejsów
    
  2. Kontrakt bez implementacji. Interfejsy definiują tylko kontrakt (metody, właściwości, zdarzenia, indeksatory) bez żadnej implementacji. Klasy abstrakcyjne mogą zawierać częściowo zaimplementowaną funkcjonalność i pola.
    interface IShape
    {
        double GetArea(); // Tylko deklaracja
    }
    
    abstract class Shape
    {
        public abstract double GetArea(); // Deklaracja
        public string Color { get; set; } // Implementacja właściwości
    
        public void DisplayColor()
        {
            Console.WriteLine($"Kolor: {Color}"); // Zaimplementowana metoda
        }
    }
    
  3. Luźne powiązanie (loose coupling). Interfejsy sprzyjają luźnemu powiązaniu między komponentami, ponieważ kod zależy od kontraktu, a nie od konkretnej implementacji klasy. Ułatwia to zamianę jednej implementacji na inną.
  4. Podział ról. Interfejsy pozwalają określić wyraźne role lub możliwości, które powinna posiadać klasa, niezależnie od jej głównego typu lub hierarchii dziedziczenia.
  5. Testowanie. Mocki i stuby do testów jednostkowych często tworzone są na podstawie interfejsów, a nie klas abstrakcyjnych, ponieważ te mogą mieć zależności lub złożoną logikę wewnętrzną.

Podsumowując: interfejsy zapewniają elastyczny mechanizm do definiowania kontraktów i osiągania polimorfizmu bez ograniczeń dziedziczenia z jednej klasy bazowej, podczas gdy klasy abstrakcyjne służą do dostarczania częściowej implementacji i podstawowego funkcjonalności, które będą uzupełniane w klasach pochodnych.