OOP: Einsatz von Vererbung

Sargnagel

Commodore Special
Mitglied seit
31.12.2001
Beiträge
477
Renomée
1
Mal eine Frage an die Leute, die OOP schon länger einsetzen: Wie verwendet ihr Vererbung? Setzt ihr es überwiegend für Code-Sharing ein, um euch Schreibarbeit zu ersparen? Oder benutzt ihr es wirklich im akademischen Sinne und baut eine logische Objekthierarchie auf, wie z.B. für die geometrischen Figuren eines einfachen Zeichenprogramms?
Oder ist die Lösung ganz banal und ihr benutzt Vererbung wie es gerade paßt? ;D

Birgt einer dieser Ansätze Vorteile für den Compiler oder ist die logische Objekthierarchie lediglich für's bessere Verständnis des Quellcodes geeignet?

Da ich demnächst ein langjähriges Projekt in Angriff nehmen werde, wollte ich unbedingt die geeignetste Strategie verwenden, damit der Quellcode (C++) möglichst flexibel, leicht wartbar und auch für dritte nachvollziehbar bleibt/ist. *chatt*
 
Um es mit C++ zu sagen: 0 ;D

D.h. ich habe das Programm schon vor ca. 2 Jahren begonnen, in C zu schreiben. Nach vielen Erweiterungen stellte sich aber heraus, daß mir die Möglichkeiten von C nicht mehr ausreichen und so habe ich beschlossen, alles nach C++ zu portieren.
 
Ich persöhnlich versuche Vererbung zu vermeiden, weil es die Klasse unübersichtlich macht - außer der Sinn ist gewichtiger. :) Dagegen finde ich Polymorphismus ("virtual") interessanter. In meinem Fall (bei meiner Diplomarbeit): Eine rein virtuelle Klasse, die alle load-balancing klassen beschreibt. Wenn ich nun eine spezielle auswählen will, kann ich ein Object der virtuellen mit der die ich haben will initialisieren - kann es also in der Laufzeti machen. Da die load-balancing Klassen aber gleiche Komponenten haben, wird auch (mehrfache) Vererbung genutzt...

Der Ursprungscode stammt nicht von mir und einige Vererbungen in anderen Bereichen habe ich auch gekillt, weil die mehr hacks waren als sinnvoll. Aber insgesamt machen beide Prinzipien (Vererbung udn Polymorphismus) sehr viel Sinn - richtig eingesetzt.
 
Ich habe Polymorphismus nicht extra aufgeführt, da es - wie ich gelernt habe - nur eine Folge der Vererbung ist. Ohne Vererbung kein Polymorphismus.
Polymorphismus ist schon eine feine Sache. ;D Ich überlege seit längerem, wie ich das vernünftig in meinem Programm umsetzen kann.
 
Schon klar. ;)

Virtuelle Klassen eigenen sich dann, wenn du z.B. in der Klasse wo du diese verwendest (und die ganze Klasse nicht rein virtuell ist) eine Funktion für etwas haben willst, von der du dir nur ein interface definierst, also du spezifizierst, was reingeht und was rauskommt. Dann kannst du mit der virtuellen, alles machen was du willst. Wie die letztendlich definiert wird, entscheidet die abgeleitete Klasse, aber das muß die "Vaterklasse" nicht weiter interessieren.

Du siehst, daß sich virt. Klassen vornehmlich für Interface Spezifikationen eignen.
 
Jo, das Pendant zu Java's abstrakten Klassen und Interfaces.

Aber wo ich das nun einsetzen soll, wird mir wohl hoffentlich in den nächsten Monaten klarer, wenn das Programm mit weiteren Features angereichert werden soll.
 
Dann würde ich sagen, fang wirklich bei NULL an, und stell ein ordentliches Konzept dafür auf. Wenn du die Anforderungen vorher richtig aufschreibst, und den Entwurf richtig machst (mit den notwendigen Diagrammen), wirst du schon weitgehend automatisch die OO richtig verwenden. Sowas ergibt sich meist aus dem konkreten Fall.
 
Dann lag ich also mit meiner Vermutung "wie's gerade paßt" gar nicht mal so verkehrt. ;)
Ich hatte deshalb gefragt, weil ich gelesen hatte, daß viele Programmierer Vererbung hauptsächlich für's Code-Sharing verwenden würden ohne Rücksicht auf eine logische Objekthierarchie.
Ich bin auf weitere Meinungen gespannt.
 
Hi.

Also ich verwende Vererbung und auch Beziehungen nicht zum Code-Sharing. Klar ist das ein positiver Nebeneffekt, aber ich habe bei meinem derzeitigen Projekt ein Konzept gemacht und dann mit Hilfe der OO-Methoden ein kleines Modell erstellt wie man die ganze Sache vereinfachen/vereinheitlichen kann.

Z.B. habe ich eine Mutterklasse IO, die allgemeine Input/Output-Operationen enthält. Jede Klasse die Dateien lesen oder schreiben muss ist ein Abkömmling der Klasse. Dann habe ich auch noch andere Mutterklassen, zur Arbeit mit Objekten und Objektlisten. Alle Klassen, die z.B. Objektlisten brauchen, erben von der Klasse.

Das Ganze als UML-Klassendiagramm verschafft einen sehr guten Überblick über das Programm und dessen Funktionsweise. Bei einer Portation würde ich mir erst mal das Programm durch den Kopf gehen lassen und dann so einheitliche Strukturen finden.

Ich persönlich finde OO ein sehr gut geeignetes Mittel, um effizient und diszipliniert zu programmieren. Zuerst sollte man sich Gedanken machen und ein Konzept erstellen, erst dann kann man später den Code hinzufügen. Außerdem bricht man Strukturen auf und schafft es ein Programm in viele kleine Objekte zu zerlegen, was das Verständnis vereinfacht.
 
Original geschrieben von Sargnagel
Ich hatte deshalb gefragt, weil ich gelesen hatte, daß viele Programmierer Vererbung hauptsächlich für's Code-Sharing verwenden würden ohne Rücksicht auf eine logische Objekthierarchie.

Sowas ist Blödsinn. OO und seine Techniken sind kein Selbstzweck, sondern sollen das erstellen und warten von Programmen vereinfachen. Das funktioniert aber nur, wenn man den ganzen Spaß sinnvoll anwendet, und nicht nach dem Motto "Wir können es, also machen wir es".
 
@skyphab:
Das klingt doch nach einem guten Konzept! Wenn die erweiterten Spezifikationen bekannt sind, werde ich das Programm in UML modellieren.
In C wollte ich schon sowas "ähnliches" realisieren, aber der Aufwand war mir zu hoch. Warum das Rad neu erfinden, wenn C++ mir alles bietet, was ich brauche!? *chatt*

@PuckPoltergeist:
Kann Dir nur zustimmen! Das würde OOP ad absurdum führen. ;)
 
Code vererbe ich eigentlich eher selten - sieht mir auch zu unsauber aus. Allerdings vererbe ich ganz gerne virtuelle Klassen ohne Code, also Interfaces. Das nehm ich dann überall wo es Code spart und halbwegs ordentlich aussieht ;D.
 
also vererbung verwende ich immer dort wo es eben sinnvoll ist, die Programme nicht aufbauscht und viel Tipparbeit erspart.
Der gesunde Mittelweg eben.

Von vererbungen Tausender Zeilen code von denen man dann schließlich 50 Zeilen nutzt, halte ich nichts, dann kopier ich mir den Code lieber raus oder bau mir eine abgespeckte DLL dafür.

z.b. in unserem Software Engineering Projekt (Ein Flipper) erben alle Komponenten bestimmte Eigenschaften wie einen Counter, bestimmte Zeichenprozeduren usw.
 
Original geschrieben von intel_hasser
Code vererbe ich eigentlich eher selten - sieht mir auch zu unsauber aus. Allerdings vererbe ich ganz gerne virtuelle Klassen ohne Code, also Interfaces. Das nehm ich dann überall wo es Code spart und halbwegs ordentlich aussieht ;D.
Inwiefern spart denn ein Interface Code? Man muß doch immer noch analog zu Java die jeweilige Funktion implementieren. *noahnung*
Original geschrieben von JKuehl
Von vererbungen Tausender Zeilen code von denen man dann schließlich 50 Zeilen nutzt, halte ich nichts, dann kopier ich mir den Code lieber raus oder bau mir eine abgespeckte DLL dafür.
Jo, da wären wir dann wieder beim Mißbrauch von Vererbung für's Code Sharing. ;)

Ich kann es kaum abwarten, mit der Entwicklung der C++ Version meines Programmes zu beginnen. ;D Dank Euch sollte mein erster Versuch in C++ von Erfolg gekrönt sein ... wie groß die Krone werden wird, sei jetzt mal dahingestellt. :]
 
Ja, aber beim Zugriff auf die Klassen kannst du dann ja Code sparen. Beispielsweise 3 verschiedene Klassentypen, die einige wenige Dinge gemeinsam haben - normalerweise bräuchtest du eine Fallunterscheidung.

In der Klasse selbst lässt sich damit nix sparen, das ist klar.
 
Jetzt verstehe ich, was Du meintest! Interfaces halt - hatte dank C ganz vergessen, wofür die eigentlich da sind. :] ;D
... ha, da fallen mir doch Möglichkeiten ein! *buck*
 
Ja, so feine Sachen wie Factories usw. ;)

Ich erbe auch eher selten auch eher selten von richtigen Klassen (programmiere im Moment nur Java, kein C++). Interfaces benutze ich recht häufig - gerade wegen dem Factory-Pattern.

Ich hab eh den Standpunkt, dass Entwurfsmuster bei der täglichen Arbeit viel hilfreicher sind den Code zu strukturieren und wiederverwendbar zu machen als die tollste Vererbung.

Das Blöde bei übertriebener Vererbung ist halt, dass es den Code sehr unübersichtlich macht und Leute, die den Code später verstehen und ändern müssen ewig brauchen bis sie ihn verstanden haben.
 
Naja, stell dir das so vor, wie einen Standard und dann die Implementierung.

Deine virtuelle Klasse ist z.b. opengl. Da steht nur drin, was es tun muß. Nun gibt es aber unterschiedlich Implementationen, wie mesa, Nvidia, ati, etc. Dammit füllst du die virtuellen member zu definierten.

Natrülich kann man das mit Geschick auch in C nachbauen, aber wieso häßlich, wenn es auch schön geht?
 
Ich weiß was abstrakte Basisklassen sind, ich verstehe nur den Zusammenhang zu den Interfaces nicht. Zu was ist eine abstrakte Basisklasse eine Schnittstelle?
 
Nein, du benutzt das als Schnittstelle. Guck doch mal vdr an, wie das mit den plugins geregelt wird.
 
Original geschrieben von DarkAvenger
Nein, du benutzt das als Schnittstelle.

Zu was? Die Klassen-Deklaration, wie z.B. in headern sind die Schnittstelle zur eigentlichen Implementierung. Zu was sind abstrakte Basisklassen Schnittstellen?
 
Ja, aber wenn du als "master" Programm *keine* Implementierung angeben willst? Die abstrakte Basisklasse ist die Schnittstelle zu was auch immer man die haben möchte.
 
So sähe ein Interface in C++ aus (bzw. könnte es so aussehen, bei C++ kann man das auf verschiedene Varianten machen):

Code:
class i
{
    virtual int a();
    virtual void b();
}

Das kannst du bei Funktionen als Parameter übergeben, sagen wir

Code:
int fa(i* p);

und auf i* kannst du eben alle Klassen zurückführen die i implementieren, also sagen wir

Code:
class a : public i
{
    int a(); // mit folgendem Funktionscode
    void b(); // mit Funktionscode
}

Also der Funktionsaufruf

Code:
fa(new a());

wäre jetzt gültig, weil a eben i implementiert.

Die OpenGL Sache ist schon ein gutes Beispiel - du kannst ja auch sowas hier machen:

Code:
class b : public i
{
    int a(); // mit folgendem Funktionscode (anders als bei a)
    void b(); // mit Funktionscode (anders als bei a)
}


i* ptr;

if(dummy==0) ptr=new a();
else ptr=new b();

Nach dem if ist es völlig egal ob wir das als a oder b deklariert haben, beide implementieren die Schnittstelle i und auf beide können wir dank i einheitlich zugreifen.
 
Zurück
Oben Unten