I literka I na naszej liście. Co oznacza, że w tym wpisie przedstawię Ci zasadę segregacji interfejsów. No właśnie, czym jest zasada segregacji interfejsów?
SOLID
S – Zasada pojedynczej odpowiedzialności (Single Responsibility Principle – SRP)
O – Zasada otwarte – zamknięte – (Open-Closed Principle – OCP)
L – Zasada podstawiania Liskov – (Liskov Substitution Principle – LSP)
I – Zasada segregacji interfejsów – (Interface Segregation Principle – ISP)
D – Zasada odwracania zależności – (Dependency Inversion Principle DIP)
Zasada Segregacji Interfejsów
Podstawą rozważań na temat tej zasady są interfejsy. Poprzez interfejs możemy rozumieć klasę abstrakcyjną z metodami abstrakcyjnymi lub zwykły interfejs. W niniejszym artykule będę posługiwał się terminem interfejs, mając na myśli obie te rzeczy.
Podczas implementacji interfejsie jesteśmy zmuszeni do zaimplementowania każdej jego składowej. Czy zdarzyło Ci się, że korzystając z jakiegoś interfejsu w nowo tworzonej klasie, nie wypełniłeś ciała którejś z jego metod? Jeżeli tak, to naruszyłeś zasadę segregacji interfejsu. A mówi ona:
Załóżmy, że implementujesz interfejs. Jeśli zauważysz, że się, że jakaś metoda lub propercja nie jest Ci w niej potrzebna i implementacja jest pusta/domyślna, to w takim przypadku powinieneś przemyśleć strukturę tego interfejsu. W takim przypadku błędnie zaprojektowałeś hierarchię. Powinieneś dokonać podziału tego interfejsu na kilka mniejszych.
Praktyczny przykład
Wszystko łatwiej zrozumieć na przykładzie. Posłużę się lekko zmodyfikowanym kodem z poprzedniego wpisu o mnemoniku SOLID.
public interface IVehicle { double Combustion { get; set; } string Name { get; set; } int WheelsCount { get; set; } void About(); } public class Car : IVehicle { public string Type { get; set; } public double Combustion { get; set; } public string Name { get; set; } public int WheelsCount { get; set; } public void About() { Console.WriteLine($"I'm {Type} - {Name} - with {Combustion}L combustion and {WheelsCount} wheels count!"); } } public class ElectricCar : IVehicle { public int BatteriesCount { get; set; } public void About() { Console.WriteLine($"I'm {Name} - with {WheelsCount} wheels count and {BatteriesCount} batteries count!"); } public double Combustion { get; set; } public string Name { get; set; } public int WheelsCount { get; set; } } internal class Program { private static void Main() { var electricCar = new ElectricCar(); var car = new Car(); car.Name = "Tesla"; car.WheelsCount = 4; car.Type = "Muscle Car"; car.Combustion = 10.5f; electricCar.Name = "Tesla"; electricCar.WheelsCount = 4; electricCar.BatteriesCount = 10; electricCar.About(); car.About(); Console.WriteLine(); Console.ReadKey(); } }
Wynik działania:

Wszystko działa poprawnie. Zwróć, proszę uwagę na kod programu, a dokładnie na klasę ElectricCar
. Właściwość Combustion
musi zostać zaimplementowana pomimo tego, że nie będzie używana. Rozwiążmy ten problem.
Sposobów na poprawienie tego problemu jest wiele. Jednym z nich jest utworzenie nowego interfejsu dla pojazdów elektrycznych dziedziczący po IVehicle
, ale przedtem należy zmodyfikować ten interfejs.
public interface IVehicle { string Name { get; set; } int WheelsCount { get; set; } void About(); } public interface IElectricVehicle : IVehicle { int BatteriesCount { get; set; } } public class Car : IVehicle { public string Type { get; set; } public double Combustion { get; set; } public string Name { get; set; } public int WheelsCount { get; set; } public void About() { Console.WriteLine($"I'm {Type} - {Name} - with {Combustion}L combustion and {WheelsCount} wheels count!"); } } public class ElectricCar : IElectricVehicle { public string Name { get; set; } public int WheelsCount { get; set; } public int BatteriesCount { get; set; } public void About() { Console.WriteLine($"I'm {Name} - with {WheelsCount} wheels count and {BatteriesCount} batteries count!"); } } internal class Program { private static void Main() { var electricCar = new ElectricCar(); var car = new Car(); car.Name = "Tesla"; car.WheelsCount = 4; car.Type = "Muscle Car"; car.Combustion = 10.5f; electricCar.Name = "Tesla"; electricCar.WheelsCount = 4; electricCar.BatteriesCount = 10; electricCar.About(); car.About(); Console.WriteLine(); Console.ReadKey(); } }
Przykład, choć naiwny przedstawił główne założenie, jakie ze sobą niesie zasada segregacji interfejsu.