Rückblick – System zur Schülerverwaltung
Teil des Abschnitts Objektorientierte Programmierung der GDScript-Journey von Coddy. Lektion 30 von 65.
Aufgabe
MittelErstelle ein kleines Schülerverwaltungssystem aus zwei Klassen.
Student in student.gd hält seine Daten privat:
_init(id, new_name)speichert die ID in einer privaten Variable und weist den Namen über den Setterstudent_namezu.student_idist schreibgeschützt und gibt die ID zurück.student_namehat einen Setter: Ein Name mit weniger als2Zeichen wird abgelehnt (der alte Name bleibt erhalten) undlast_errorwird zuName must be at least 2 characters. Bei einem gültigen Namen wirdlast_errorgeleert.add_grade(course, grade)speichert die Note für den Kurs in einem privaten Dictionary (eine neue Note für denselben Kurs ersetzt die alte) und gibttruezurück. Eine Note unter0oder über100wird nicht gespeichert und gibtfalsezurück.averageist eine schreibgeschützte berechnete Eigenschaft: der Durchschnitt der Noten alsfloatoder0.0, wenn keine Noten vorhanden sind.course_count()gibt die Anzahl der Kurse mit einer Note zurück.
StudentRegistry in student_registry.gd speichert die Schüler in einem privaten Dictionary, wobei die ID als Schlüssel dient:
add_student(student)gibtfalsezurück und ändert nichts, wenn die ID bereits vergeben ist; andernfalls speichert die Methode den Schüler und gibttruezurück.remove_student(id)gibt zurück, ob ein Schüler entfernt wurde.get_student(id)gibt den Schüler odernullzurück.top_student()gibt den Schüler mit dem höchsten Durchschnitt zurück (bei Gleichstand den zuerst hinzugefügten) odernull, wenn das Register leer ist.get_ids()gibt die IDs in der Reihenfolge zurück, in der die Schüler hinzugefügt wurden.
Der bereitgestellte Code liest die Anzahl der Befehle ein und führt anschließend pro Zeile einen Befehl aus: add ID NAME, grade ID COURSE GRADE, rename ID NAME, remove ID, show ID, tamper ID (versucht, student_id und average zu überschreiben, was keine Wirkung haben darf), top und list. Bei dieser Eingabe:
10
add 1001 Alice Smith
add 1002 Bob
grade 1001 Math 90
grade 1001 Art 85
grade 1002 Math 95
grade 1002 Art 120
rename 1002 B
show 1002
top
listgibt der Code Folgendes aus:
Added Alice Smith (1001)
Added Bob (1002)
Alice Smith: Math = 90
Alice Smith: Art = 85
Bob: Math = 95
Invalid grade: 120
Rejected: Name must be at least 2 characters
ID: 1002, Name: Bob, Courses: 1, Average: 95.00
Top: Bob (95.00)
ID: 1001, Name: Alice Smith, Courses: 2, Average: 87.50
ID: 1002, Name: Bob, Courses: 1, Average: 95.00Dein Code gehört in student.gd und student_registry.gd. main.gd enthält den bereitgestellten Ein-/Ausgabecode und darf nicht bearbeitet werden.
Probier es selbst
extends Node
func _ready():
# Vorgegebener Ein-/Ausgabecode: unverändert lassen
var registry := StudentRegistry.new()
var count := int(OS.read_string_from_stdin())
for i in count:
var parts := OS.read_string_from_stdin().split(" ", true, 2)
var command := parts[0]
if command == "top":
var best := registry.top_student()
if best == null:
print("Top: none")
else:
print("Top: %s (%.2f)" % [best.student_name, best.average])
continue
if command == "list":
for listed_id in registry.get_ids():
print_student(registry.get_student(listed_id))
continue
var id := int(parts[1])
if command == "add":
var student := Student.new(id, parts[2])
if student.last_error != "":
print("Rejected: " + student.last_error)
elif registry.add_student(student):
print("Added %s (%d)" % [student.student_name, id])
else:
print("Duplicate ID: %d" % id)
continue
if command == "remove":
print(("Removed %d" if registry.remove_student(id) else "No student %d") % id)
continue
var student := registry.get_student(id)
if student == null:
print("No student %d" % id)
elif command == "grade":
var grade_parts := parts[2].split(" ")
if student.add_grade(grade_parts[0], int(grade_parts[1])):
print("%s: %s = %s" % [student.student_name, grade_parts[0], grade_parts[1]])
else:
print("Invalid grade: " + grade_parts[1])
elif command == "rename":
student.student_name = parts[2]
if student.last_error != "":
print("Rejected: " + student.last_error)
else:
print("Renamed to " + student.student_name)
elif command == "tamper":
# Versucht, die schreibgeschützten Eigenschaften zu überschreiben
student.student_id = 0
student.average = 100.0
print_student(student)
else:
print_student(student)
func print_student(student: Student) -> void:
print("ID: %d, Name: %s, Courses: %d, Average: %.2f" % [student.student_id, student.student_name, student.course_count(), student.average])
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienEinführung in die OOPKlassen vs. ObjekteDas Schlüsselwort selfMethodenEigenschaftenKonstruktor (_init)Wiederholung – Einfacher Taschenrechner4Polymorphie
Methodenüberschreibung erneut betrachtetDuck-TypisierungAbstrakte Klassen und MethodenSchnittstellendesignRückblick – Formrechner2Klassenattribute
Instanz- vs. statische VariablenStatische FunktionenProperty-SetterProperty-GetterPrivat nach KonventionWiederholung – Bankkontenverwaltung5Kapselung
Öffentliche und private MemberValidierung mit SetternInformationsverbergenSchreibgeschützte EigenschaftenRückblick – System zur Schülerverwaltung8Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungInnere KlassenNodes als KomponentenRefCounted vs. NodeEnums in Klassen11Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen3Vererbung
Grundlegende VererbungDas Schlüsselwort superMethodenüberschreibungVererbungskettenTypprüfungen mit isWiederholung – Mitarbeiterhierarchie6Spezielle Methoden
Einführung in virtuelle MethodenDie _to_string-MethodeBenutzerdefinierte IteratorenRückblick – Benutzerdefinierte Liste9Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFactory-MusterBeobachter-MusterStrategie-Muster12Abschließende Herausforderungen
E-Learning-PlattformBankensystemEntwicklung von SpielfigurenFahrzeugvermietungÜbe selbstständig: Online-GDScript-Compiler