Menu
Coddy logo textTech

Słowo kluczowe final dla klas

Część sekcji Programowanie obiektowe ścieżki Dart w Coddy. Lekcja 40 z 110.

Czasami chcesz uniemożliwić rozszerzanie klasy. Słowo kluczowe final, zastosowane do klasy, uniemożliwia dziedziczenie po niej innym klasom.

final class DatabaseConnection {
  String connectionString;
  
  DatabaseConnection(this.connectionString);
  
  void connect() {
    print('Connected to $connectionString');
  }
}

// To spowodowałoby błąd podczas kompilacji:
// class CustomConnection extends DatabaseConnection { }

Oznaczenie klasy jako final jest przydatne, gdy jej rozszerzenie mogłoby naruszyć jej zamierzone działanie lub gwarancje bezpieczeństwa. Na przykład klasa zarządzająca wrażliwymi zasobami może wymagać, aby jej metody nie były nadpisywane w nieoczekiwany sposób.

Dart 3 wprowadził również powiązane modyfikatory: base wymusza użycie extends (a nie implements) przez podklasy, a sealed ogranicza dziedziczenie do tej samej biblioteki. Na razie skup się na final jako najprostszym sposobie całkowitego zablokowania klasy.

Używaj klas final, gdy masz pewność, że projekt klasy jest kompletny, a dziedziczenie tylko powodowałoby problemy. Nie nadużywaj jednak tej możliwości — większość klas zyskuje na tym, że pozostają otwarte na rozszerzenia.

challenge icon

Wyzwanie

Łatwy

Zbudujmy bezpieczny system konfiguracji, który pokazuje, kiedy i dlaczego warto uniemożliwić rozszerzanie klasy. Utworzysz klasę finalną, która zarządza ustawieniami aplikacji, zapewniając, że jej zachowania nie będzie można zmienić przez dziedziczenie.

Podzielisz kod na dwa pliki:

  • config.dart: Zdefiniuj tutaj klasy konfiguracji:
    • Klasa final class AppConfig, której nie można rozszerzać. Powinna mieć właściwości String appName i String version, konstruktor przyjmujący obie wartości oraz metodę display(), która wyświetla [appName] v[version]
    • Zwykła (niefinalna) klasa Feature z właściwościami String name i bool enabled, konstruktorem przyjmującym obie wartości oraz metodą status(), która wyświetla [name]: [enabled ? 'ON' : 'OFF']
    • Klasa ExperimentalFeature, która rozszerza Feature i dodaje właściwość String warning. Zastąp metodę status(), używając @override, aby najpierw wywołać wersję rodzica za pomocą super.status(), a następnie wyświetlić Warning: [warning]
  • main.dart: Zaimportuj plik konfiguracji i pokaż różnicę między klasami finalnymi a zwykłymi:
    • Utwórz AppConfig z appName 'MyApp' i version '2.0.1', a następnie wywołaj display()
    • Wyświetl pusty wiersz
    • Utwórz Feature o nazwie 'Dark Mode' i z enabled ustawionym na true, a następnie wywołaj status()
    • Wyświetl pusty wiersz
    • Utwórz ExperimentalFeature o nazwie 'AI Assistant', z enabled ustawionym na false i warning równym 'May be unstable', a następnie wywołaj status()

Zwróć uwagę, że AppConfig jest oznaczona jako final, ponieważ jej zachowanie związane z konfiguracją powinno pozostać spójne i bezpieczne — żadna podklasa nie powinna móc zmienić sposobu zarządzania ustawieniami. Tymczasem Feature pozostaje otwarta na rozszerzenia, dzięki czemu ExperimentalFeature może dodawać wyspecjalizowane zachowanie.

Oczekiwany wynik:

MyApp v2.0.1

Dark Mode: ON

AI Assistant: OFF
Warning: May be unstable

Spróbuj swoich sił

import 'config.dart';

void main() {
  // TODO: Utwórz obiekt AppConfig z appName 'MyApp' i version '2.0.1'
  // Następnie wywołaj display()
  
  // TODO: Wypisz pustą linię
  
  // TODO: Utwórz obiekt Feature z name 'Dark Mode' i enabled true
  // Następnie wywołaj status()
  
  // TODO: Wypisz pustą linię
  
  // TODO: Utwórz obiekt ExperimentalFeature z name 'AI Assistant',
  // enabled false i warning 'May be unstable'
  // Następnie wywołaj status()
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator Dart online