Metody abstrakcyjne
Część sekcji Programowanie obiektowe ścieżki Dart w Coddy. Lekcja 44 z 110.
Metoda abstrakcyjna to metoda zadeklarowana w klasie abstrakcyjnej, która nie ma treści. Definiuje sygnaturę metody, ale pozostawia implementację każdej podklasie. Każda klasa rozszerzająca klasę abstrakcyjną musi nadpisać wszystkie metody abstrakcyjne, w przeciwnym razie sama również będzie abstrakcyjna.
abstract class Animal {
// Metoda abstrakcyjna – nie ma ciała, musi zostać zaimplementowana przez podklasy
String makeSound();
// Metoda konkretna – ma ciało, wspólna dla wszystkich podklas
void breathe() {
print('Breathing...');
}
}
class Dog extends Animal {
@override
String makeSound() {
return 'Woof!'; // Trzeba dostarczyć implementację
}
}
class Cat extends Animal {
@override
String makeSound() {
return 'Meow!'; // Inna implementacja, ta sama sygnatura
}
}Jeśli podklasa zapomni zaimplementować metodę abstrakcyjną, Dart zgłosi błąd kompilacji. Na tym właśnie polega sens — metody abstrakcyjne wymuszają przestrzeganie kontraktu. Masz gwarancję, że każda podklasa będzie miała tę metodę, więc możesz bezpiecznie wywołać ją na dowolnej instancji typu abstrakcyjnego.
// Możesz użyć typu abstrakcyjnego jako typu zmiennej
Animal a = Dog();
print(a.makeSound()); // Hau!
Animal b = Cat();
print(b.makeSound()); // Miau!Metody abstrakcyjne różnią się od metod konkretnych w klasie abstrakcyjnej. Metody konkretne mają treść i są dziedziczone bez zmian. Metody abstrakcyjne nie mają treści i muszą zostać przesłonięte.
Możesz łączyć oba podejścia w tej samej klasie abstrakcyjnej, aby współdzielić niektóre zachowania, a jednocześnie wymuszać na podklasach definiowanie własnych dla innych.
| Cecha | Metoda abstrakcyjna | Metoda konkretna |
|---|---|---|
| Ma treść | Nie | Tak |
| Trzeba nadpisać | Tak | Nie |
| Cel | Wymuszenie kontraktu | Współdzielenie zachowania |
| Gdzie | Tylko klasa abstrakcyjna | Dowolna klasa |
Wyzwanie
ŁatwyZbudujmy kalkulator kształtów, który pokaże działanie metod abstrakcyjnych. Zdefiniujesz klasę abstrakcyjną z metodami abstrakcyjnymi, które każdy kształt musi implementować na swój sposób, a następnie użyjesz tych kształtów za pośrednictwem wspólnego interfejsu.
Podzielisz kod na cztery pliki:
shape.dart: Zdefiniuj klasę abstrakcyjnąShapez polemfinalcolor(String) i konstruktorem, który je inicjalizuje. Zadeklaruj dwie metody abstrakcyjne:double area()idouble perimeter(). Dodaj również konkretną metodędescribe(), która wypisujeA [color] shape with area: [area] and perimeter: [perimeter]. Ponieważarea()iperimeter()są abstrakcyjne, każda podklasa dostarczy własne obliczenia, aledescribe()działa dla wszystkich bez konieczności nadpisywania.circle.dart: Utwórz klasęCircle, która rozszerzaShape. Ma polefinalradius(double). Jej konstruktor przyjmujecoloriradius, a następnie przekazujecolordosuper. Zaimplementujarea(), aby zwracała3.14 * radius * radius, orazperimeter(), aby zwracała2 * 3.14 * radius.rectangle.dart: Utwórz klasęRectangle, która rozszerzaShape. Ma polafinalwidthiheight(oba typu double). Jej konstruktor przyjmujecolor,widthiheight, a następnie przekazujecolordosuper. Zaimplementujarea(), aby zwracaławidth * height, orazperimeter(), aby zwracała2 * (width + height).main.dart: Zaimportuj wszystkie pliki. UtwórzCircleo kolorze'red'i promieniu5.0, a takżeRectangleo kolorze'blue', szerokości4.0i wysokości6.0. Wywołajdescribe()dla każdego kształtu. Następnie utwórzList<Shape>zawierającą oba kształty, przejdź pętlą przez listę i wypiszArea: [area]dla każdego kształtu.
Oczekiwany wynik:
A red shape with area: 78.5 and perimeter: 31.400000000000002
A blue shape with area: 24.0 and perimeter: 20.0
Area: 78.5
Area: 24.0Spróbuj swoich sił
import 'shape.dart';
import 'circle.dart';
import 'rectangle.dart';
void main() {
// TODO: Utwórz Circle o kolorze 'red' i promieniu 5.0
// TODO: Utwórz Rectangle o kolorze 'blue', szerokości 4.0 i wysokości 6.0
// TODO: Wywołaj describe() dla koła
// TODO: Wywołaj describe() dla prostokąta
// TODO: Utwórz List<Shape> zawierającą obie figury
// TODO: Przejdź przez listę i wypisz "Area: [area]" dla każdej figury
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy OOP
Pliki zewnętrzneBiblioteki i importyWprowadzenie do OOPKlasy a obiektySłowo kluczowe thisMetodyZmienne instancjiPodstawy konstruktorówPowtórka – prosty kalkulator4Bezpieczeństwo wartości null
Wprowadzenie do bezpieczeństwa wartości nullTypy dopuszczające null i niedopuszczające nullOperatory ? i !Słowo kluczowe late a bezpieczeństwo wartości nullOperatory uwzględniające nullBezpieczeństwo wartości null w klasachPodsumowanie — system profili użytkowników7Klasy abstrakcyjne i interfejsy
Klasy abstrakcyjneMetody abstrakcyjneInterfejsy w DartInterfejsy niejawneImplementowanie a rozszerzanieWiele interfejsówPowtórka — kalkulator kształtów10Kolekcje i typy generyczne
Przegląd List, Set i MapKolekcje bezpieczne typowoKlasy generyczneMetody generyczneOgraniczenia typów generycznychIterable i IteratorPowtórka — generyczne przechowywanie danych13Zaawansowane koncepcje OOP
Kompozycja a dziedziczenieMetody rozszerzająceKlasy wywoływalneKlasy zapieczętowane (Dart 3)Rekordy (Dart 3)Wzorce i dopasowywanie (3.0)Typy wyliczeniowe z metodami16Projekt: Zarządzanie biblioteką
Omówienie projektuKlasy książek i użytkowników2Konstruktory w Dart
Konstruktor domyślnyKonstruktory nazwaneListy inicjalizująceKonstruktory stałeKonstruktory fabryczneKonstruktory przekierowującePodsumowanie — budowanie kształtów5Hermetyzacja
Elementy publiczne a prywatneKonwencja prefiksu _Prywatność na poziomie bibliotekiGettery i settery — szczegółowoUkrywanie informacjiPodsumowanie — dane uczniów8Domieszki
Wprowadzenie do domieszekTworzenie domieszekKorzystanie z wielu domieszekSłowo kluczowe on w domieszkachDomieszka a dziedziczenieDomieszka a interfejsPodsumowanie – system zwierząt11Metody specjalne
Nadpisanie toString()Nadpisanie hashCode i ==Interfejs ComparableMetoda call()Nadpisanie noSuchMethodPodsumowanie — własna kolekcja14Wzorce projektowe, część 1
Wprowadzenie do wzorców projektowychWzorzec SingletonWzorzec FactoryWzorzec ObserverWzorzec Strategy3Właściwości klas
Elementy instancji a elementy statycznePola final i constZmienne inicjalizowane z opóźnieniemMetody i pola statyczneGettery i setteryPowtórzenie – menedżer kont bankowych6Dziedziczenie
Podstawy dziedziczeniaSłowo kluczowe superPrzesłanianie metodAdnotacja @overrideSłowo kluczowe final dla klasKonstruktory i dziedziczeniePowtórzenie – hierarchia pracowników9Polimorfizm
Podstawy polimorfizmuPolimorfizm za pomocą interfejsówSprawdzanie typu w czasie działaniaOperatory is i asSłowo kluczowe covariantPodsumowanie — procesor płatnościPoćwicz samodzielnie: Kompilator Dart online