Ein Ratschlag, den ich mir vor langer Zeit gewünscht hätte, ist:
Übernehmen Sie die Vererbung nicht.
Dies ist eine wirklich einfache Falle für einen Anfänger (imho), da es eines der großen Konzepte in OOP ist, über die alle reden.
Grundsätzlich sollten Sie die Vererbung nur dort verwenden, wo es wirklich wirklich Sinn macht - Datentypen, einige Widget-Hierarchien, Dinge, bei denen die Beziehung ist-so offensichtlich ist, dass irgendjemand sie benutzt hätte. Andernfalls sollten Sie Objekte in andere Objekte einfügen und aufrufen, um die Funktionalität (Zusammensetzung) zu ändern.
Seien Sie nicht versucht, einfach eine Menge abstrakter Methoden zu definieren und sie mehrfach zu überschreiben, um sie anders zu implementieren, wenn Sie eine einzelne Klasse haben und ein Konstruktorobjekt injizieren können, das eine Schnittstelle implementiert, die Sie aufrufen, um die variablen Funktionen auszuführen das hättest du sonst in die abstrakten Methoden gesteckt.
Dies wird zu viel einfacherem und wiederverwendbarem Code führen (meiner Erfahrung nach) und auch testbarer.