Interfejsy niejawne
Część sekcji Programowanie obiektowe ścieżki Dart w Coddy. Lekcja 46 z 110.
Ponieważ każda klasa w Dart automatycznie definiuje interfejs, możesz użyć dowolnej klasy jako interfejsu — nawet klasy konkretnej z pełną implementacją. To właśnie nazywamy interfejsem niejawnym.
Rozważ klasę z właściwościami i metodami:
class Logger {
String prefix = '[LOG]';
void log(String message) {
print('$prefix $message');
}
void clear() {
print('Clearing logs...');
}
}Gdy inna klasa implementuje Logger, musi zapewnić własną implementację wszystkiego — w tym właściwości prefix:
class FileLogger implements Logger {
@override
String prefix = '[FILE]';
@override
void log(String message) {
print('$prefix Writing to file: $message');
}
@override
void clear() {
print('Deleting log file...');
}
}Oto kluczowy wniosek: gdy używasz implements, mówisz: „moja klasa będzie miała taki sam kształt” — te same metody i właściwości. Nie dziedziczysz żadnego kodu, konstruktorów ani wartości domyślnych. Obiecujesz jedynie dopasować się do struktury interfejsu.
Dzięki temu niejawne interfejsy są przydatne do tworzenia wymiennych komponentów. Kod, który oczekuje obiektu Logger, może współpracować z każdą klasą implementującą jego interfejs, niezależnie od tego, jak działa ona wewnętrznie.
Wyzwanie
ŁatwyZbudujmy system powiadomień, który pokazuje, jak klasy konkretne mogą pełnić rolę niejawnych interfejsów. Utworzysz bazową klasę powiadomienia, a następnie zaimplementujesz ją w zupełnie inny sposób, pokazując, że implements wymaga samodzielnego dostarczenia wszystkich składowych.
Podzielisz kod na dwa pliki:
notification.dart: Zdefiniuj tutaj klasy powiadomień:- Klasę
Notificationz właściwościąString channelustawioną na'default', metodąsend(String message), która wyświetla[channel]: [message], oraz metodągetStatus(), która zwraca ciąg znaków'Notification ready' - Klasę
EmailNotification, która implementujeNotification. Ponieważ używaszimplements, musisz podać własną właściwośćchannel(ustaw ją na'email'), własną metodęsend(), która wyświetlaSending email: [message], oraz własną metodęgetStatus(), która zwraca'Email service active' - Klasę
PushNotification, która implementujeNotification. Ustaw jejchannelna'push', spraw, bysend()wyświetlałaPush alert: [message], a metodagetStatus()zwracała'Push service connected'
- Klasę
main.dart: Zaimportuj plik z powiadomieniami i pokaż, jak różne klasy mogą implementować ten sam niejawny interfejs, uzyskując zupełnie różne zachowania:- Utwórz obiekt
EmailNotificationi obiektPushNotification - Dla każdego powiadomienia wyświetl jego status za pomocą
getStatus(), a następnie wywołajsend()z wiadomością'Hello World' - Wyświetl pustą linię między tymi dwoma powiadomieniami
- Utwórz obiekt
Pamiętaj: gdy używasz implements, nie dziedziczysz żadnego kodu z Notification. Obiecujesz jedynie, że twoja klasa będzie miała taki sam kształt — te same właściwości i metody. Każda klasa implementująca zapewnia własną, kompletną implementację.
Oczekiwany wynik:
Email service active
Sending email: Hello World
Push service connected
Push alert: Hello WorldSpróbuj swoich sił
import 'notification.dart';
void main() {
// TODO: Utwórz instancję EmailNotification
// TODO: Wyświetl status powiadomienia e-mail za pomocą getStatus()
// TODO: Wyślij wiadomość 'Hello World' za pomocą powiadomienia e-mail
// TODO: Wyświetl pustą linię
// TODO: Utwórz instancję PushNotification
// TODO: Wyświetl status powiadomienia push za pomocą getStatus()
// TODO: Wyślij wiadomość 'Hello World' za pomocą powiadomienia push
}
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