Różnice między klasami abstrakcyjnymi a interfejsami
W programowaniu obiektowym w C++ kluczowe jest zrozumienie, jak projektować hierarchię klas. Do tworzenia wzorców zachowań używamy klas abstrakcyjnych oraz interfejsów (które w C++ są po prostu specyficzną formą klasy abstrakcyjnej).
1. Klasa Abstrakcyjna (Tożsamość: "IS-A")
Klasa abstrakcyjna w C++ to taka, która posiada przynajmniej jedną czystą funkcję wirtualną (zapisaną jako = 0).
- Brak instancji: Nie można utworzyć obiektu takiej klasy (np.
Urzadzenie u;wywoła błąd). - Dziedziczenie: Klasa pochodna musi nadpisać czyste funkcje wirtualne, aby można było stworzyć jej obiekty.
- Pola i Metody: Może posiadać zwykłe zmienne (pola) oraz metody z gotowym kodem, które będą wspólne dla wszystkich dzieci.
- Słowo kluczowe
virtualioverride: Używamyvirtualw bazie i (opcjonalnie, ale zalecane)overridew klasie pochodnej, by uniknąć błędów.
2. Interfejs (Umiejętność: "CAN-DO")
W C++ nie ma słowa interface. Interfejs to po prostu klasa, która posiada tylko i wyłącznie czyste funkcje wirtualne i nie ma żadnych pól (zmiennych).
- Wielokrotne dziedziczenie: C++ pozwala jednej klasie dziedziczyć po wielu innych klasach. Pozwala to "składać" obiekt z wielu umiejętności.
- Kontrakt: Implementując interfejs, klasa obiecuje, że dostarczy kod dla wszystkich jego funkcji.
Kod z lekcji
Ten kod pokazuje różnicę: Urządzenie (baza) vs Sterowanie (umiejętność).
Podsumowanie
Głównym celem lekcji było zrozumienie, że w programowaniu obiektowym nie liczy się tylko "pisanie kodu", ale projektowanie relacji między obiektami.
1. Zapamiętaj różnicę (Złota zasada)
- Klasa Abstrakcyjna to fundament. Mówi nam, czym obiekt JEST (relacja IS-A). Używamy jej, gdy obiekty mają wspólne cechy i logikę (np. każde urządzenie ma model i stan włączenia).
- Interfejs (Klasa czysto abstrakcyjna) to kontrakt. Mówi nam, co obiekt POTRAFI (relacja CAN-DO). Używamy go, by nadać umiejętność klasom, które nie muszą być ze sobą spokrewnione (np. pilotem możemy sterować telewizorem, ale i inteligentną roletą).
2. Szybkie porównanie techniczne
| Cecha | Klasa Abstrakcyjna | Interfejs (w C++) |
|---|---|---|
| Definicja | Zawiera przynajmniej jedną funkcję = 0. |
Zawiera tylko funkcje = 0. |
| Pola (dane) | Może posiadać zmienne (np. string model). |
Nie posiada pól (brak stanu). |
| Dziedziczenie | Klasa pochodna dziedziczy tożsamość. | Klasa implementuje zachowanie. |
| Cel | Unikanie powtarzania kodu (wspólna baza). | Elastyczność i polimorfizm. |
3. Słowa kluczowe – Twoi sprzymierzeńcy
virtual– "Hej, ta funkcja może być inna w przyszłości (w klasach pochodnych)".= 0– "Ta funkcja nie ma tutaj sensu, musisz ją napisać w konkretnej klasie".override– "Sprawdź mnie, kompilatorze! Chcę nadpisać funkcję z bazy i nie chcę zrobić literówki".
4. Dlaczego to robimy?
Dzięki stosowaniu tych struktur nasz kod jest:
- Rozszerzalny: Możemy dodać nową klasę (np.
Projektor), nie zmieniając ani jednej linii kodu w funkcjach obsługujących urządzenia. - Bezpieczny: Kompilator pilnuje, byśmy nie zapomnieli o ważnych funkcjach (np. uruchomieniu urządzenia).
- Czytelny: Od razu widzimy, jakie urządzenia mamy w systemie i które z nich obsługują sterowanie pilotem.
💡 Ostatnia myśl:
"Klasa abstrakcyjna to geny, które dostajemy po rodzicach. Interfejs to certyfikat ukończenia kursu – nie ważne, kim jesteś, ważne, że umiesz to, co jest na dyplomie."