Sobes.tech
Junior

Na czym polega istota abstrakcji?

sobes.tech AI

Odpowiedź od AI

Abstrakcja w Flutter, podobnie jak w programowaniu ogólnie, sprowadza się do ukrywania złożonej implementacji i dostarczania uproszczonego interfejsu do interakcji. Osiąga się to poprzez tworzenie widoków wysokiego poziomu, które ukrywają szczegóły i pozwalają pracować z koncepcjami, a nie z konkretnymi implementacjami.

Główne idee:

  • Ukrywanie szczegółów: Złożona logika lub struktura danych są ukryte za prostym interfejsem.
  • Uproszczenie użycia: Programista korzysta z abstrakcyjnej reprezentacji, nie zagłębiając się w szczegóły implementacji.
  • Zwiększenie elastyczności: Zmiany w wewnętrznej implementacji nie wpływają na kod korzystający z abstrakcji, o ile interfejs pozostaje ten sam.
  • Ponowne użycie: Abstrakcyjne komponenty mogą być używane w różnych częściach aplikacji.

Przykłady w Flutter:

  • Widżety: Widżety są abstrakcjami nad elementami interfejsu użytkownika. Używamy Container, Row, Column i innych, nie znając ich wewnętrznej implementacji w szczegółach.
  • Programowanie asynchroniczne: Future i Stream abstrahują pracę z operacjami asynchronicznymi, ukrywając szczegóły obsługi strumieni i zdarzeń.
  • Wzorce architektoniczne: Użycie wzorców takich jak BLoC, Provider czy Riverpod jest formą abstrakcji, która oddziela UI od logiki biznesowej.

Przykład kodu z użyciem abstrakcji:

// Abstrakcyjna klasa dla źródła danych
abstract class DataSource {
  Future<String> fetchData();
}

// Implementacja korzystająca z HTTP
class HttpDataSource implements DataSource {
  @override
  Future<String> fetchData() async {
    // Tu złożona logika pracy z żądaniem HTTP
    return "Dane z HTTP";
  }
}

// Implementacja korzystająca z lokalnego magazynu
class LocalDataSource implements DataSource {
  @override
  Future<String> fetchData() async {
    // Tu złożona logika pracy z lokalnym magazynem
    return "Dane z lokalnego magazynu";
  }
}

// Klasa korzystająca z abstrakcji DataSource
class Repository {
  final DataSource dataSource;

  Repository(this.dataSource);

  Future<String> getData() {
    return dataSource.fetchData();
  }
}

W tym przykładzie Repository komunikuje się tylko z abstrakcją DataSource, nie martwiąc się o to, skąd dokładnie pochodzą dane (HTTP, lokalny magazyn itp.). Umożliwia to łatwą zmianę źródła danych bez modyfikacji kodu Repository.