Menu
Coddy logo textTech

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.

CechaMetoda abstrakcyjnaMetoda konkretna
Ma treśćNieTak
Trzeba nadpisaćTakNie
CelWymuszenie kontraktuWspółdzielenie zachowania
GdzieTylko klasa abstrakcyjnaDowolna klasa
challenge icon

Wyzwanie

Łatwy

Zbudujmy 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ą Shape z polem final color (String) i konstruktorem, który je inicjalizuje. Zadeklaruj dwie metody abstrakcyjne: double area() i double perimeter(). Dodaj również konkretną metodę describe(), która wypisuje A [color] shape with area: [area] and perimeter: [perimeter]. Ponieważ area() i perimeter() są abstrakcyjne, każda podklasa dostarczy własne obliczenia, ale describe() działa dla wszystkich bez konieczności nadpisywania.
  • circle.dart: Utwórz klasę Circle, która rozszerza Shape. Ma pole final radius (double). Jej konstruktor przyjmuje color i radius, a następnie przekazuje color do super. Zaimplementuj area(), aby zwracała 3.14 * radius * radius, oraz perimeter(), aby zwracała 2 * 3.14 * radius.
  • rectangle.dart: Utwórz klasę Rectangle, która rozszerza Shape. Ma pola final width i height (oba typu double). Jej konstruktor przyjmuje color, width i height, a następnie przekazuje color do super. Zaimplementuj area(), aby zwracała width * height, oraz perimeter(), aby zwracała 2 * (width + height).
  • main.dart: Zaimportuj wszystkie pliki. Utwórz Circle o kolorze 'red' i promieniu 5.0, a także Rectangle o kolorze 'blue', szerokości 4.0 i wysokości 6.0. Wywołaj describe() dla każdego kształtu. Następnie utwórz List<Shape> zawierającą oba kształty, przejdź pętlą przez listę i wypisz Area: [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.0

Spró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
}
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