Menu
Coddy logo textTech

Ograniczenia typów generycznych

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

Czasami potrzebujesz, aby typ generyczny miał określone możliwości. Na przykład jeśli chcesz porównywać elementy lub uzyskiwać dostęp do określonych właściwości, nieograniczony typ T nie gwarantuje, że te funkcje będą dostępne. Ograniczenia typów generycznych pozwalają ograniczyć parametry typów do określonych typów lub ich podklas.

Użyj słowa kluczowego extends, aby ograniczyć parametr typu:

class NumberBox<T extends num> {
  T value;
  
  NumberBox(this.value);
  
  T doubled() => (value * 2) as T;
}

void main() {
  var intBox = NumberBox<int>(5);
  var doubleBox = NumberBox<double>(3.5);
  
  print(intBox.doubled());    // 10
  print(doubleBox.doubled()); // 7.0
  
  // var stringBox = NumberBox<String>('hi');  // Błąd!
}

Ponieważ T extends num, kompilator wie, że value obsługuje operacje numeryczne, takie jak mnożenie. Bez tego ograniczenia wywołanie value * 2 zakończyłoby się błędem.

Ograniczenia działają również z własnymi hierarchiami klas:

abstract class Animal {
  String get name;
}

class Dog extends Animal {
  String get name => 'Dog';
}

class Shelter<T extends Animal> {
  List<T> animals = [];
  
  void add(T animal) => animals.add(animal);
  
  void printNames() {
    for (var animal in animals) {
      print(animal.name);  // Bezpieczne: T gwarantuje, że 'name' istnieje
    }
  }
}

Ograniczenia typów generycznych łączą elastyczność typów generycznych z bezpieczeństwem wynikającym z wiedzy o tym, jakie operacje są dostępne dla danego typu.

challenge icon

Wyzwanie

Łatwy

Zbudujmy kalkulator statystyk, który działa tylko z typami liczbowymi! Utworzysz klasę generyczną z ograniczeniem, które zapewnia, że można jej używać tylko z liczbami, dzięki czemu bezpiecznie wykonasz operacje matematyczne na przechowywanych wartościach.

Podzielisz kod na dwa pliki:

  • stats.dart: Utwórz generyczną klasę Stats<T extends num>, która zarządza listą wartości liczbowych:
    • List<T> o nazwie values do przechowywania liczb
    • Konstruktor, który inicjalizuje listę podanymi wartościami
    • Metodę sum(), która zwraca sumę wszystkich wartości jako num
    • Metodę min(), która zwraca najmniejszą wartość jako T
    • Metodę max(), która zwraca największą wartość jako T
    • Metodę printStats(), która wyświetla statystyki w sformatowanej postaci
  • main.dart: Zaimportuj plik stats i pokaż działanie ograniczonej klasy generycznej z różnymi typami liczbowymi:
    • Utwórz Stats<int> z wartościami [10, 25, 5, 30, 15] i wywołaj printStats()
    • Wypisz pustą linię
    • Utwórz Stats<double> z wartościami [3.5, 1.2, 4.8, 2.1] i wywołaj printStats()

Metoda printStats() powinna wyświetlać trzy wiersze z sumą, wartością minimalną i maksymalną. Ponieważ T extends num, możesz bezpiecznie używać operatorów porównania i operacji arytmetycznych na wartościach — czego nie dałoby się zrobić w przypadku nieograniczonego typu generycznego.

Oczekiwany wynik:

Sum: 85
Min: 5
Max: 30

Sum: 11.6
Min: 1.2
Max: 4.8

Spróbuj swoich sił

import 'stats.dart';

void main() {
  // TODO: Utwórz Stats<int> z wartościami [10, 25, 5, 30, 15]
  // i wywołaj printStats()
  
  // TODO: Wypisz pustą linię
  
  // TODO: Utwórz Stats<double> z wartościami [3.5, 1.2, 4.8, 2.1]
  // i wywołaj printStats()
}
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