Benutzer mit den meisten Antworten
Kann eine geerbte Klasse auch die Instanz erben?

Frage
-
Hallo,
ich habe eine total blöde Frage.
Sagen wir mal ich habe eine Klasse mit den wichtigsten Funktionen, in diesem Fall für Sound. Jetzt habe ich eine weitere Klasse, mit ein paar Zusatzfunktionen, z.B. FX.
Jetzt würde ich z.B. die FX-Klasse anfangen zu schreiben und sagen, erbe von Sound. Soweit, so gut.
Jetzt instanziiere ich die Sound-Klasse und sie läuft. In einer anderen Routine möchte ich jetzt einen Effekt dazuschalten. Jetzt habe ich natürlich nicht das Handle in der Sound-Klasse, weil, es wird ja "blöderweise" ebenfalls neu instanziiert.
Aber wie kann ich es lösen, dass ich eine Basis-Klasse habe und später weitere Funktionen mit weiteren Klassen hinzufügen, die wiederum auf die aktuelle Instanz der Basis-Klasse zurückgreift?
Bisher habe ich das immer so gelöst, dass ich die Sound-Klasse in die andere FX-Klasse mit rüber genommen habe und dort in einer Variable abgelegt habe und dann über die Variable zugegriffen habe.
Ist das die einzige Möglichkeit? Oder ginge es auch wie oben von mir beschrieben?
Gruß
Andy
Antworten
-
Hallo Andreas,
Also, habe ich mir jetzt fest vorgenommen, konsequent zu trennen. Wenn ich eine App habe, wo nur kurz mal ein Ton abgespielt werden soll (übertrieben ausgedrückt), dann brauche ich weder Effekte, noch einen Spectrum-Analyser, oder Equalizer oder Recording, Mp3Tags etc.
Das soll (ähnlich wie bei einem Plugin) dann im jeweiligen Projekt hinzukommen, wenn es auch wirklich benötigt wird.das klingt für mich aber so als ob Du das Problem doch etwas falsch angehen willst.
In dem Fall wäre es meiner Meinung nach nicht sinnvoll, das über Vererbung zu lösen. Denn bspw. haben die Mp3Tags doch gar nichts mit deiner Sound Klasse zu tun. Daher ist es IMHO nicht zielführend, diese Klasse von Sound erben zu lassen.
Solltest Du innerhalb der Mp3Tags Klasse eine Instanz von Sound benötigen, kannst Du die entweder als Eigenschaft dauerhaft hinterlegen oder Du übergibst bei dem Methodenaufruf in eine Mp3Tags Methode die Sound Instanz. Dasselbe gilt für Recording, ...
Plugin hin, Plugin her. Ich würde die Logik in Klassen trennen und jede Klasse für sich als eigenständiges Element sehen. Natürlich gibt es mal Querverweise aber wenn man einer bestimmten Hierarchie folgt, ist das überschaubar und auch sinnvoll nutzbar.
D.h. ich würde eine Library mit deinen Klassen wie Sound, Effects, Equalizer, Mp3Tags, ... erstellen und diese dann in deinen Apps als Verweis mit einbinden. Wenn Du in der App dann nur die Sound brauchst, ok. Wenn doch noch Mp3Tags, dann stehen die auch gleich zur Verfügung.
Dafür musst Du aber erstmal deine Denkweise komplett über den Haufen werfen und die Logik deiner Klassen überarbeiten und auf kleine Stücke runterbrechen. Reduziere die Abhängigkeiten auf ein Minimum. Arbeite nicht mit globalen Objekten/Instanzen, sondern mit Eigenschaften/Variablen in den Instanzen, die eigens (oder über DI, ...) übergeben werden und vermeide damit
zuppel ich an einer Variable rum, fängt es irgendwo an zu quietschen.
HTH
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport- Als Antwort markiert AndreasMahub Freitag, 8. Januar 2021 15:25
-
Hi Andreas,
... Gut, Peter meinte eher entweder/oder, aber ich habe halt mal probiert, was passiert, wenn ich es kombiniere. ...
Vererbung, partielle Klassen und Erweiterungsmethoden sind 3 verschiedene Mittel, die niemals als "oder" zu verstehen sind. Das gleiche Ziel ist nicht entweder mit diesem Mittel ODER mit dem anderen Mittel zu erreichen. Vererbung erzeugt eine "erweiterte" Speichernutzung, partielle Klassen "zerteilen lediglich" den Programmcode in verschiedene Dateien, die immer in einem Übersetzungslauf als Summenmenge aller Anweisungen übersetzt werden. Erweiterungsmethoden stellen zusätzliche Methoden bereit, die nicht die Struktur der Speichernutzung verändern, sondern lediglich zusätzlichen Speicherplatz im Stack bereitstellen, d.h. nur innerhalb des Aufrufes einer der Erweiterungsmethode nutzbar sind.
--
Best Regards / Viele Grüße
Peter Fleischer (former MVP for Developer Technologies)
Homepage, Tipps, Tricks- Als Antwort markiert AndreasMahub Freitag, 8. Januar 2021 15:25
Alle Antworten
-
Hi Andreas,
deine Fragestellung ist etwas unklar. Wichtig ist zu verstehen, dass eine Klasse der Code ist, der anzuarbeiten ist. Die Instanz dagegen ist lediglich Speicherplatz, den der Code nutzt, indem im Code immer über eine Basis-Adresse (Pointer / Verweis) und den im Übersetzungsverlauf erzeugten Displacements (Verschiebungen) auf die einzelnen Speicherbereiche zugegriffen wird.Den Code einer Klasse und damit den Umfang der Möglichkeiten kann man über verschiedene Wege erweitern:
1. Vererbung
2. Partielle Klassen
3. Extension methods
Welche der Methoden genutzt wird bzw. werden kann, hängt von den Ausgangsbedingungen und den Zielen ab. Ich denke, zu deiner Beschreibung sollten am besten Erweiterungsmethoden (extension methods) passen. Damit kann man einer Klasse weitere Methoden hinzufügen.
--
Best Regards / Viele Grüße
Peter Fleischer (former MVP for Developer Technologies)
Homepage, Tipps, Tricks -
Hallo Peter,
ich habe mich eben an eine Erweiterungsmethode gesetzt und ja, ist ganz nett. Beispiel:
namespace ExtensionsTests { public static class SoundFx { public static int Reverb(this Sound _Sound) { // Zum Testen das aktuelle Sound-Handle zurückgeben... return _Sound.Handle; } } }
Funktioniert. Das eigentliche Handle kommt zurück. Da es aber eine Statische Klasse ist (und scheinbar auch nichts anderes erlaubt ist), kann ich keine Zustände speichern. Als Beispiel (ACHTUNG! GEHT NATÜRLICH NICHT!):
namespace ExtensionsTests { public static class SoundFx { private string _Abc = "Guten Morgen..."; public static int Reverb(this Sound _Sound) { // Wir merken uns was _Abc = "Nix 'Guten Morgen'... Es ist jetzt " + DateTime.Now.ToShortTimeString(); // Zum Testen das aktuelle Sound-Handle zurückgeben... return _Sound.Handle; } } }
Aber gibt es vielleicht trotzdem einen Kniff, wo man sich dann Zustände merken kann? Ich weiß das es keine "Erweiterungsklassen" gibt :-) Aber so in etwa versuche ich es zu beschreiben, was mir etwas schwer fällt. die SoundFx-Klasse braucht man nicht ständig, aber wenn man sie braucht, lädt man sie dazu und bietet mir die entsprechenden Funktionen an.
Gruß
Andy
- Bearbeitet AndreasMahub Freitag, 8. Januar 2021 08:21
-
Hallo,
wartet mal, ich hab eine Idee. Eine Kombination aus Partial und Erweiterungsklassen?
Ich lege in der zweiten Klassen-Bibliothek eine Partial-Klasse Sound an, wo ich nur die privaten Variablen für SoundFx reinlege und die SoundFx-Klasse enthält die oben gezeigte Erweiterungs-Methoden. Wäre das der richtige Ansatz?
Gruß
Andy -
Jetzt würde ich z.B. die FX-Klasse anfangen zu schreiben und sagen, erbe von Sound. Soweit, so gut.
Jetzt instanziiere ich die Sound-Klasse und sie läuft. In einer anderen Routine möchte ich jetzt einen Effekt dazuschalten. Jetzt habe ich natürlich nicht das Handle in der Sound-Klasse, weil, es wird ja "blöderweise" ebenfalls neu instanziiert.
Hallo Andy,
zeig doch mal deinen Code (am besten ein auf das absolut notwendigste reduzierte Beispiel, welches aber in sich lauffähig sein sollte).
Ich nehme an, dein Fehler ist "Jetzt instanziiere ich die Sound Klasse". Das machst Du von außen? (Also nicht innerhalb der FX Klasse? Frage nur sicherheitshalber, da das unnötig wäre)
Instanziier die FX Klasse, nicht die Sound Klasse. Dann hast Du alles, was Du brauchst.
So oder so: Jede Instanz existiert für sich alleine und hat mit anderen Instanzen nichts zu tun.
Nach den weiteren Posts denke ich, dass Du evtl. ein grundlegendes Problem mit dem Verständnis von Vererbung, ... hast. (Alternativ hab ich ein grundlegendes Problem, deine Beschreibung zu verstehen :))
Aber so in etwa versuche ich es zu beschreiben, was mir etwas schwer fällt. die SoundFx-Klasse braucht man nicht ständig, aber wenn man sie braucht, lädt man sie dazu und bietet mir die entsprechenden Funktionen an.
Also entweder instanzierst Du die SoundFx Klasse oder eben nicht. Wenn SoundFx von Sound erbt, hast Du in einer Instanz von SoundFx alles, was auch Sound hat.
Wenn Du in SoundFx nicht von Sound erben willst, kannst Du dir einfach eine Eigenschaft vom Typ "Sound" erstellen und bspw. im Konstruktor von SoundFx die Sound Instanz übergeben.
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport
- Bearbeitet Stefan FalzModerator Freitag, 8. Januar 2021 09:53
-
Hallo Stefan,
>>> Nach den weiteren Posts denke ich, dass Du evtl. ein grundlegendes Problem mit dem Verständnis von Vererbung, ... hast.
Jein, also, behaupte ich mal. Das mit der Vererbung habe ich schon verstanden. Und habe ich auch bereits angewendet, so ist das nicht.
Ein Beispiel: Ich habe die eigentliche Sound-Klasse mit den grundlegenden Sound-Funktionen. Dann habe ich einen Player, der nur die Abspielfunktionen mit den dazugehörigen Events usw. bereitstellt. Das funktioniert auch alles.
Jetzt enthält meine Sound-Klasse aber ganz ganz viele Funktionen, die nicht immer benötigt werden. Angefangen habe ich damit 2007 in VB.NET. Jetzt, 2020 will ich komplett umsteigen auf C#. Als ich 2007 mit dem OOP angefangen habe, war ich noch Sprichwörtlich "Grün hinter den Ohren". Wenn ich heute in meinen Quellcode reinschaue, lege ich immer wieder meine Hände ins Gesicht und schüttle mit dem Kopf.
Die Sound-Klasse hat mittlerweile mehr als 2.800 Zeilen Quellcode und wird immer unübersichtlicher. Ich traue mich schon gar nichts mehr anzufassen. Ist wie Mikado, zuppel ich an einer Variable rum, fängt es irgendwo an zu quietschen.
Also, habe ich mir jetzt fest vorgenommen, konsequent zu trennen. Wenn ich eine App habe, wo nur kurz mal ein Ton abgespielt werden soll (übertrieben ausgedrückt), dann brauche ich weder Effekte, noch einen Spectrum-Analyser, oder Equalizer oder Recording, Mp3Tags etc.
Das soll (ähnlich wie bei einem Plugin) dann im jeweiligen Projekt hinzukommen, wenn es auch wirklich benötigt wird.
Daher auch meine Idee (danke an Peter), mit der Kombination aus Partial, Vererbung und Erweiterungsmethoden. Gut, Peter meinte eher entweder/oder, aber ich habe halt mal probiert, was passiert, wenn ich es kombiniere. Eine "nur Vererbung" hätte (aus meiner Sicht) die Folge, dass eine Vererbungskette entsteht. Ist in einem der Kettenglieder eine Macke, haut irgendwann der Rest der Kette nicht mehr hin. Oder sehe ich das soooo falsch? :-)
Korrigiert mich, ihr seid die Profis :-)
Gruß
Andy -
Hallo Andreas,
Also, habe ich mir jetzt fest vorgenommen, konsequent zu trennen. Wenn ich eine App habe, wo nur kurz mal ein Ton abgespielt werden soll (übertrieben ausgedrückt), dann brauche ich weder Effekte, noch einen Spectrum-Analyser, oder Equalizer oder Recording, Mp3Tags etc.
Das soll (ähnlich wie bei einem Plugin) dann im jeweiligen Projekt hinzukommen, wenn es auch wirklich benötigt wird.das klingt für mich aber so als ob Du das Problem doch etwas falsch angehen willst.
In dem Fall wäre es meiner Meinung nach nicht sinnvoll, das über Vererbung zu lösen. Denn bspw. haben die Mp3Tags doch gar nichts mit deiner Sound Klasse zu tun. Daher ist es IMHO nicht zielführend, diese Klasse von Sound erben zu lassen.
Solltest Du innerhalb der Mp3Tags Klasse eine Instanz von Sound benötigen, kannst Du die entweder als Eigenschaft dauerhaft hinterlegen oder Du übergibst bei dem Methodenaufruf in eine Mp3Tags Methode die Sound Instanz. Dasselbe gilt für Recording, ...
Plugin hin, Plugin her. Ich würde die Logik in Klassen trennen und jede Klasse für sich als eigenständiges Element sehen. Natürlich gibt es mal Querverweise aber wenn man einer bestimmten Hierarchie folgt, ist das überschaubar und auch sinnvoll nutzbar.
D.h. ich würde eine Library mit deinen Klassen wie Sound, Effects, Equalizer, Mp3Tags, ... erstellen und diese dann in deinen Apps als Verweis mit einbinden. Wenn Du in der App dann nur die Sound brauchst, ok. Wenn doch noch Mp3Tags, dann stehen die auch gleich zur Verfügung.
Dafür musst Du aber erstmal deine Denkweise komplett über den Haufen werfen und die Logik deiner Klassen überarbeiten und auf kleine Stücke runterbrechen. Reduziere die Abhängigkeiten auf ein Minimum. Arbeite nicht mit globalen Objekten/Instanzen, sondern mit Eigenschaften/Variablen in den Instanzen, die eigens (oder über DI, ...) übergeben werden und vermeide damit
zuppel ich an einer Variable rum, fängt es irgendwo an zu quietschen.
HTH
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport- Als Antwort markiert AndreasMahub Freitag, 8. Januar 2021 15:25
-
Hi Andreas,
... Gut, Peter meinte eher entweder/oder, aber ich habe halt mal probiert, was passiert, wenn ich es kombiniere. ...
Vererbung, partielle Klassen und Erweiterungsmethoden sind 3 verschiedene Mittel, die niemals als "oder" zu verstehen sind. Das gleiche Ziel ist nicht entweder mit diesem Mittel ODER mit dem anderen Mittel zu erreichen. Vererbung erzeugt eine "erweiterte" Speichernutzung, partielle Klassen "zerteilen lediglich" den Programmcode in verschiedene Dateien, die immer in einem Übersetzungslauf als Summenmenge aller Anweisungen übersetzt werden. Erweiterungsmethoden stellen zusätzliche Methoden bereit, die nicht die Struktur der Speichernutzung verändern, sondern lediglich zusätzlichen Speicherplatz im Stack bereitstellen, d.h. nur innerhalb des Aufrufes einer der Erweiterungsmethode nutzbar sind.
--
Best Regards / Viele Grüße
Peter Fleischer (former MVP for Developer Technologies)
Homepage, Tipps, Tricks- Als Antwort markiert AndreasMahub Freitag, 8. Januar 2021 15:25
-
Guten Abend,
gut, ich werde eure Ratschläge befolgen und es wieder so wie vorher machen. Ich habe nämlich an die nächste Klasse (also z.B. der MP3Tags) die eigentliche Sound-Klasse weitergegeben und lokal gespeichert, dachte aber immer, dass es dann "unsauber" wird.
Im Grunde ist damit meine Eingangsfrage beantwortet, es ist nicht machbar.
Ich danke euch beiden recht herzlich, zeigt es mir, ich war eigentlich schon auf dem richtigen Weg und das andere von mir war einfach mal "Quatsch" :-)
Gruß
Andy -
Im Grunde ist damit meine Eingangsfrage beantwortet, es ist nicht machbar.
Hallo Andy,
deine Vermutung ist nicht korrekt. Denn die Fragestellung war schon die falsche, da Du eigentlich ganz was anderes wolltest als eine Vererbung von Klassen.
Eine Instanz einer Klasse, die von einer anderen Klasse erbt, hat immer bereits Zugriff auf die Instanz ihre Basisklasse, da diese integraler Bestandteil ist (ohne die Basis könnte die abgeleite Klasse ja gar nicht existieren). Damit wäre die eigentlich gestellte Frage mit "Ja. Aber das ist automatisch immer so." zu beantworten.
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport
- Bearbeitet Stefan FalzModerator Samstag, 9. Januar 2021 10:51