Klasy i metody abstrakcyjne
Część sekcji Programowanie obiektowe ścieżki GDScript w Coddy. Lekcja 23 z 65.
Niektóre klasy istnieją wyłącznie po to, by po nich dziedziczyć. Każda figura ma pole powierzchni, ale nie możesz go obliczyć, dopóki nie wiesz, czy figura jest kołem, czy prostokątem. Oznacz taką klasę jako @abstract, w wierszu nad class_name:
# shape.gd
@abstract
class_name Shape
extends RefCounted
@abstract func area() -> float
@abstract func perimeter() -> float
func describe() -> String:
return "Area %.1f, perimeter %.1f" % [area(), perimeter()]@abstract func ma sygnaturę i nie ma ciała: nie ma dwukropka ani kodu po niej. Oznacza to, że każde dziecko musi zdefiniować tę metodę. describe() jest zwykłą metodą; dzieci ją dziedziczą i może już wywoływać metody abstrakcyjne.
Nie możesz utworzyć obiektu klasy abstrakcyjnej. Shape.new() zatrzymuje program, zanim się uruchomi, z komunikatem Parse Error: Cannot construct abstract class "Shape".
Klasa pochodna, która implementuje każdą metodę abstrakcyjną, jest zwykłą klasą:
# rectangle.gd
class_name Rectangle
extends Shape
var width: float
var height: float
func _init(w: float, h: float) -> void:
width = w
height = h
func area() -> float:
return width * height
func perimeter() -> float:
return 2 * (width + height)var rect := Rectangle.new(4.0, 6.0)
print(rect.describe())Area 24.0, perimeter 20.0Jeśli klasa potomna pominie jedną z nich, Godot zgłosi to przed uruchomieniem: Class "Square" must implement "Shape.perimeter()" and other inherited abstract methods or be marked as "@abstract". Dzięki temu każdy obiekt, który możesz utworzyć, ma metody area() i perimeter().
Klasa abstrakcyjna nadal może mieć zmienne i metodę _init(). Klasy potomne wywołują ją za pomocą super(), jak zwykle.
Wyzwanie
ŁatwySklep akceptuje dwie metody płatności. Każda płatność ma kwotę i paragon, ale opłata i nazwa zależą od metody.
- Ustaw
PaymentMethodjako klasę abstrakcyjną i zadeklaruj dwie metody abstrakcyjne:fee() -> floatorazmethod_name() -> String. Napiszreceipt(), która zwracaNAME: paid AMOUNT, fee FEE, total TOTAL, podając każdą liczbę z dwoma miejscami po przecinku (suma to kwota powiększona o opłatę). CreditCard: opłata wynosi 3% kwoty (amount * 0.03), a nazwa toCredit card.BankTransfer: opłata wynosi1.5albo0.0, gdy kwota wynosi100lub więcej, a nazwa toBank transfer.
Klasy potomne używają konstruktora PaymentMethod. Dostarczony kod odczytuje liczbę kolejnych płatności, a następnie jeden wiersz dla każdej płatności: card AMOUNT lub transfer AMOUNT. Wypisuje każdy paragon i sumę opłat. Dla card 50 i transfer 120 wypisuje:
Credit card: paid 50.00, fee 1.50, total 51.50
Bank transfer: paid 120.00, fee 0.00, total 120.00
Total fees: 1.50Umieść swój kod w plikach payment_method.gd, credit_card.gd i bank_transfer.gd. main.gd zawiera dostarczony kod wejścia/wyjścia i nie można go edytować.
Spróbuj swoich sił
extends Node
func _ready():
# Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
var count := int(OS.read_string_from_stdin())
var total_fees := 0.0
for i in count:
var p := OS.read_string_from_stdin().split(" ")
var payment: PaymentMethod
if p[0] == "card":
payment = CreditCard.new(float(p[1]))
else:
payment = BankTransfer.new(float(p[1]))
print(payment.receipt())
total_fees += payment.fee()
print("Total fees: %.2f" % total_fees)
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy programowania obiektowego
Pliki zewnętrzneWprowadzenie do programowania obiektowegoKlasy a obiektySłowo kluczowe selfMetodyWłaściwościKonstruktor (_init)Powtórka – prosty kalkulator4Polimorfizm
Ponowne omówienie przesłaniania metodDuck typingKlasy i metody abstrakcyjneProjektowanie interfejsówPowtórzenie – kalkulator kształtów7Sygnały
Czym jest sygnał?Deklarowanie i emitowanieŁączenie z sygnałamiSygnały z argumentamiPodsumowanie — system zdrowia10Wzorce projektowe, część 2
Wzorzec poleceniaWzorzec adapteraWzorzec dekoratoraWzorzec metody szablonowejWzorzec stanuWzorzec kompozytu2Właściwości klas
Zmienne instancji a zmienne statyczneFunkcje statyczneSettery właściwościGettery właściwościPrywatne z konwencjiPodsumowanie — menedżer kont bankowych5Enkapsulacja
Elementy publiczne i prywatneWalidacja za pomocą setterówUkrywanie informacjiWłaściwości tylko do odczytuPodsumowanie – system ewidencji uczniów8Zaawansowane koncepcje OOP
Kompozycja a dziedziczenieKlasy wewnętrzneWęzły jako komponentyRefCounted a NodeTypy wyliczeniowe w klasach11Projekt: Zarządzanie biblioteką
Przegląd projektuKlasy książki i użytkownika3Dziedziczenie
Podstawy dziedziczeniaSłowo kluczowe superNadpisywanie metodŁańcuchy dziedziczeniaSprawdzanie typów za pomocą isPodsumowanie – hierarchia pracowników6Metody specjalne
Wprowadzenie do metod wirtualnychMetoda _to_stringWłasne iteratoryPodsumowanie — własna lista9Wzorce projektowe — część 1
Wprowadzenie do wzorców projektowychWzorzec SingletonWzorzec FactoryWzorzec ObserverWzorzec StrategyPoćwicz samodzielnie: Kompilator GDScript online