Kiedy używać klasy abstrakcyjnej, a kiedy interfejsu w języku C #

Projektując aplikacje, ważne jest, aby wiedzieć, kiedy używać klasy abstrakcyjnej, a kiedy interfejsu. Chociaż klasy abstrakcyjne i interfejsy wydają się pod pewnymi względami podobne, istnieją kluczowe różnice, które określą, który wybór jest najlepszy dla tego, co próbujesz osiągnąć. W tym wpisie na blogu omówię te różnice i jak zdecydować, kiedy ich użyć.

Krótka odpowiedź: Klasa abstrakcyjna umożliwia tworzenie funkcji, które podklasy mogą implementować lub zastępować. Interfejs umożliwia jedynie zdefiniowanie funkcjonalności, a nie jej implementację. I chociaż klasa może rozszerzać tylko jedną klasę abstrakcyjną, może korzystać z wielu interfejsów. 

Wyjaśnienie klasy abstrakcyjnej języka C #

Klasa abstrakcyjna to specjalny typ klasy, której nie można utworzyć instancji. Klasa abstrakcyjna jest dziedziczona przez podklasy, które implementują lub przesłaniają jej metody. Innymi słowy, klasy abstrakcyjne są zaimplementowane częściowo lub wcale. Możesz mieć funkcjonalność w swojej klasie abstrakcyjnej - metody w klasie abstrakcyjnej mogą być zarówno abstrakcyjne, jak i konkretne. Klasa abstrakcyjna może mieć konstruktory - jest to jedna z głównych różnic między klasą abstrakcyjną a interfejsem. Możesz skorzystać z klas abstrakcyjnych, aby zaprojektować komponenty i określić pewien poziom typowych funkcji, które muszą być implementowane przez klasy pochodne.

Interfejs C # wyjaśniony

Interfejs jest w zasadzie umową - nie ma żadnej implementacji. Interfejs może zawierać tylko deklaracje metod; nie może zawierać definicji metod. Nie możesz też mieć żadnych danych członków w interfejsie. Podczas gdy klasa abstrakcyjna może zawierać definicje metod, pola i konstruktory, interfejs może mieć tylko deklaracje zdarzeń, metod i właściwości. Metody zadeklarowane w interfejsie muszą być implementowane przez klasy, które implementują interfejs. Zauważ, że klasa może implementować więcej niż jeden interfejs, ale rozszerzyć tylko jedną klasę. Klasa implementująca interfejs powinna implementować wszystkie swoje elementy członkowskie. Podobnie jak w przypadku klasy abstrakcyjnej, nie można utworzyć wystąpienia interfejsu.

Powinienem użyć klasy abstrakcyjnej czy interfejsu?

Klasy abstrakcyjne zapewniają elastyczność polegającą na posiadaniu pewnych konkretnych metod i niektórych innych metod, które powinny implementować klasy pochodne. Z drugiej strony, jeśli używasz interfejsów, musisz zaimplementować wszystkie metody w klasie, która rozszerza interfejs. Klasa abstrakcyjna jest dobrym wyborem, jeśli masz plany na przyszłą ekspansję - tj. Jeśli w hierarchii klas prawdopodobne jest przyszłe rozwinięcie. Jeśli chcesz zapewnić obsługę przyszłej rozbudowy przy użyciu interfejsów, musisz rozszerzyć interfejs i utworzyć nowy.

Z drugiej strony, w razie potrzeby łatwo jest dodać nowy interfejs do hierarchii. Jeśli jednak masz już klasę abstrakcyjną w swojej hierarchii, nie możesz dodać kolejnej - tj. Możesz dodać klasę abstrakcyjną tylko wtedy, gdy żadna nie jest dostępna. Powinieneś użyć interfejsu, jeśli chcesz mieć umowę na pewne zachowanie lub funkcjonalność. Nie powinieneś używać interfejsu, jeśli musisz napisać ten sam kod dla metod interfejsu. W takim przypadku należy użyć klasy abstrakcyjnej, zdefiniować metodę raz i użyć jej ponownie w razie potrzeby. Używaj interfejsów, aby oddzielić kod aplikacji od określonych jej implementacji lub ograniczyć dostęp do elementów członkowskich określonego typu.

Jak stwierdza dokumentacja interfejsów firmy Microsoft:

Korzystając z interfejsów, można na przykład uwzględnić w klasie zachowanie z wielu źródeł. Ta funkcja jest ważna w języku C #, ponieważ język nie obsługuje wielokrotnego dziedziczenia klas. Ponadto, jeśli chcesz symulować dziedziczenie struktur, musisz użyć interfejsu, ponieważ w rzeczywistości nie mogą one dziedziczyć z innej struktury lub klasy.

Niejawne i jawne implementacje interfejsu

Interfejsy można zaimplementować niejawnie lub jawnie. Pozwólcie, że wyjaśnię, czym różnią się te dwie implementacje. Rozważmy interfejs o nazwie IBusinessLogic.

publiczny interfejs IBusinessLogic

{

   void Initialize ();

}

Następująca klasa o nazwie BusinessLogicimplementuje IBusinessLogicinterfejs.

klasa publiczna BusinessLogic: IBusinessLogic

{

   public void Initialize ()

   {

       // Jakiś kod

   }

}

Możesz BusinessLogicjawnie utworzyć instancję klasy, a następnie wywołać Initialize()metodę, jak pokazano poniżej.

 IBusinessLogic businessLogic = new BusinessLogic ();

businessLogic.Initialize ();

Poniższy fragment kodu ilustruje sposób IBusinessLogicniejawnej implementacji interfejsu.

klasa publiczna BusinessLogic: IBusinessLogic

{

   void IBusinessLogic.Initialize ()

   {

   }

}

Możesz teraz wywołać Initialize()metodę w ten sam sposób, używając odwołania do IBusinessLogicinterfejsu. Różnica między tymi dwoma podejściami polega na tym, że gdy implementujesz interfejs jawnie w swojej klasie, jesteś ograniczony do wywoływania metody interfejsu przy użyciu tylko odwołania do interfejsu. Dlatego poniższy fragment kodu nie zadziała, tj. Nie będzie się kompilował.

 BusinessLogic businessLogic = nowy BusinessLogic ();

businessLogic.Initialize ();

Jak zrobić więcej w C #:

  • Kiedy używać klasy abstrakcyjnej, a kiedy interfejsu w języku C #
  • Jak pracować z AutoMapper w C #
  • Jak używać wyrażeń lambda w C #
  • Jak pracować z delegatami Action, Func i Predicate w C #
  • Jak pracować z delegatami w C #
  • Jak zaimplementować prosty rejestrator w C #
  • Jak pracować z atrybutami w C #
  • Jak pracować z log4net w C #
  • Jak zaimplementować wzorzec projektu repozytorium w C #
  • Jak pracować z odbiciem w C #
  • Jak pracować z Filesystemwatcher w C #
  • Jak wykonać leniwą inicjalizację w C #
  • Jak pracować z MSMQ w C #
  • Jak pracować z metodami rozszerzającymi w C #
  • Jak nam wyrażenia lambda w C #
  • Kiedy używać słowa kluczowego volatile w języku C #
  • Jak używać słowa kluczowego yield w języku C #
  • Jak zaimplementować polimorfizm w C #
  • Jak zbudować własny harmonogram zadań w C #
  • Jak pracować z RabbitMQ w C #
  • Jak pracować z krotką w C #
  • Eksplorowanie metod wirtualnych i abstrakcyjnych w C #