Hallo! Ich bin Konstantin, neu hier, und hab direkt eine Frage. Bisher habe ich mit ein paar Controllerfamilien gearbeitet, aber nur in C und hin und wieder Assembler. Aus Neugier auf c++ und (vor allem dann) weil ich im Moment echt zu wenig Zeit habe, bin ich auf Arduino gekommen. Das System ist ein Roboter, heißt Zumo und dazu gibt es (natürlich) eine Library. So nun die Frage. Für die Motoren gibt es eine motors lib. Die bietet allerdings nur recht rudimentäre Funktionalität. Habe ich schon für meine Bedürfnisse erweitert, als da wären geregelte Geradeausfahrt, Streckenfahrt und in Ansätzen Kurven. Das funktinoiert so lala und jetzt kommt meine c++ Frage. Eine my_motors Klasseist das Ziel und ich frage mich ob man das so machen kann/sollte/könnte dass a) my_motors von der originalen motors Klasse erbt. Oder b) ob eine my_motors Klasse ein member von der motors Klasse erhät. Im Fall a hätte my_motors alle eigenschaften von motors, was ja gewollt wäre und nur eine zusatzfunktionalität in Form von den oben erwähnten Funktionalitäten. Ist es richtig dass dann die Initialisierung die in motors erledigt wird passiert, wenn ich ein Objekt my_motors alege? Im Fall b würde ein my_motors Objekt was dann nur die neuen Funktionen kann jedesmal Funktionen von dem motors Objekt aufrufen. Hat so was Einflüsse auf das Laufzeitverhalten oder ist quasi nur der Inhalt einer Funktion interessant und es ist egal ob die zu einer anderen Klasse gehört oder der eigenen. Ich WEISS es ist etws wirr und ich habe heute Nachmittag zig Anläufe gemacht, mein Problem und meine Frage aufzubereiten. Hätte mir besser gelingen können - hoffentlich versteht der eine oder andere mich :-)
Hi, Bei der Frage ob Member oder vererben, kommst du immer mit der “ist ein oder hat ein“ Frage weiter. In deinem Fall solltest du ableiten. Den Rest der Fragen würd ich mit ja beantworten. ;) Tschö
Hi, ich würde zu b) raten. Ich gehe davon aus, dass du eine neue Abstraktionsebene hinzufügst und deine neue Funktionalität nicht über das bestehende Interface benutzt wird. Möglicherweise stellst du später fest, dass du eine andere Klasse für die (gleiche) Basisfunktionalität verwenden willst. Mit Vererbung würdest du eine sehr starke Bindung eingehen. Auch wenn jeder mit OOP zuerst Vererbung verbindet: Im allgemeinen sollte man sie so sparsam wie möglich einsetzen. Nur wenn du einen Client hast, der ohne Kenntnis der (privaten) Unterschiede wahlweise die originale oder deine Klasse einsetzen können soll, wäre Vererbung angezeigt. Die Wahl hat aber keinen nennenswerten Einfluss auf das Laufzeitverhalten. Viel Erfolg!
C++-Coder schrieb: > Die Wahl hat aber keinen nennenswerten Einfluss auf das > Laufzeitverhalten. sicher? Jede Funktion muss man erst ein der neuen Klasse selber implementieren. Und dann die passende Funktion von dem anderen Objekt aufrufen. Wenn das Objekt dazu eine VTable hat lässt sich das auch nicht ohne weiteres wegoptimieren. Ich bin auch fürs Vererben in diesem Fall.
Ich bin für B. Beim Implementieren kommen immer Aspekte rein, an die man noch nicht gedacht hat. Sowas kann ich mit B einfacher lösen. Damit ist man flexibler. Wenn alles fertig ist, kann man immer noch aus B ein A machen. Dann kann man entscheiden ob damit alles abgedeckt ist.
Hi, ich würde zu a) raten. Dein Motor ist ja nichts anderes als ein Motor, nur mit ein wenig erweiterter Funktionalität. Dein Motor hat ja keinen Motor, sondern ist selbst einer -- hier ist also der Beziehungstyp "is-a" angezeigt, deswegen natürlich die Vererbung. HTH, Sheeva
:
Bearbeitet durch User
C++-Coder schrieb: > ich würde zu b) raten. > > Ich gehe davon aus, dass du eine neue Abstraktionsebene hinzufügst Der OP beschreibt doch relativ klar, daß er genau das nicht tut. Er hat nur ein wenig zusätzliche Funktionalität eingebaut. > Auch wenn jeder mit OOP zuerst Vererbung verbindet: Im allgemeinen > sollte man sie so sparsam wie möglich einsetzen. Diese Aussage kann ich beim besten Willen nicht nachvollziehen. Gerade in diesem Falle springt es einem doch geradezu ins Gesicht, daß sein Motor nichts anderes als ein erweiterter Motor ist: also Vererbung, was sonst?
Hallo Konstantin, dein my_motor (my_* sind die mit abstand blödesten Namen, denn das my_ hat exakt überhaupt keinen Informations-Inhalt), klingt für mich eher nach einem Regler, der auf einem Motor arbeitet. Dem entsprechend könnte man auch eine Funktion Kurvenfahrt() implementieren, die dann eben einen Motor als Argument nimmt. Ansonsten sollte man öffentliche (public) Vererbung möglichst Sparsam einsetzen. Ist ein my_motor wirklich ein Motor? Oder ist es in Deinem Fall nicht evtl. eher ein Regler? mfg Torsten
Torsten R. schrieb: > Hallo Konstantin, > dein my_motor (my_* sind die mit abstand blödesten Namen, denn das my_ > hat exakt überhaupt keinen Informations-Inhalt), klingt für mich eher > nach einem Regler, der auf einem Motor arbeitet. Sowas wie: my_class, my_car, my_person sieht man in Beispielen zur OOP hundertfach. Irgendwann muss jemand mal damit abgefangen haben, und die anderen haben es wohl einfach übernommen anstatt sich bessere Namen auszudenken. > Dem entsprechend könnte man auch eine Funktion Kurvenfahrt() > implementieren, die dann eben einen Motor als Argument nimmt. Nach Möglichkeit bitte nicht deutsch und englisch mischen. Ein my_motor ist wohl ein englischer Motor - der hat keine Kurvenfahrt. ;-) Hm, anscheinend heißt Kurvenfahrt auf englisch "cornering". Wusste ich nicht. Wieder was gelernt.
:
Bearbeitet durch User
Mark B. schrieb: > Nach Möglichkeit bitte nicht deutsch und englisch mischen. kann durchaus in Firmem üblich sein. Es macht kein Sinn deutsche Fachbegriffe zu übersetzen oder Get und Set zu übersetzen.
Peter II schrieb: > Mark B. schrieb: >> Nach Möglichkeit bitte nicht deutsch und englisch mischen. > > kann durchaus in Firmem üblich sein. Es macht kein Sinn deutsche > Fachbegriffe zu übersetzen oder Get und Set zu übersetzen. Ich kenne den Mischmasch aus eigener Berufserfahrung nur zu gut. In vielen Fällen dürfte das eher historisch so gewachsen sein als bewusst so gewollt. Nebenbei bemerkt: Wer OOP richtig macht, braucht weitgehend kein get() und set(). Eigentlich sollen Objekte über Nachrichten miteinander kommunizieren. http://www.javaworld.com/article/2073723/core-java/why-getter-and-setter-methods-are-evil.html
Mark B. schrieb: > Nebenbei bemerkt: > Wer OOP richtig macht, braucht weitgehend kein get() und set(). dann ist wohl 95% alles OOP Libs falsch? Bei Sprachen die Propertys haben mag da ja noch gehen. > Eigentlich sollen Objekte über Nachrichten miteinander kommunizieren. Das mag ein Ansatz sein, aber ob der immer richtig ist bezweifle ich.
Peter II schrieb: > Mark B. schrieb: >> Nebenbei bemerkt: >> Wer OOP richtig macht, braucht weitgehend kein get() und set(). > dann ist wohl 95% alles OOP Libs falsch? Bei Sprachen die Propertys > haben mag da ja noch gehen. Nur weil etwas oft benutzt wird, bedeutet es nicht dass es so auch gut und richtig ist. Wer seine Klassen per Default immer mit getter- und setter-Methoden ausstattet, der hat vermutlich kaum viel Zeit darauf verwendet sich ein wirklich gutes Software-Design zu überlegen. Meinetwegen mögen getter und setter in manchen Fällen sinnvoll sein, aber ganz sicher nicht in allen. Es stimmt schon: "Don't ask for the information you need to do the work; ask the object that has the information to do the work for you."
:
Bearbeitet durch User
Mark B. schrieb: > Nur weil etwas oft benutzt wird, bedeutet es nicht dass es so auch gut > und richtig ist. eigentlich schon, denn wenn es unbrauchbar währe hätte man es durch etwas besseres ersetzt. > Wer seine Klassen per Default immer mit getter- und setter-Methoden > ausstattet, der hat vermutlich kaum viel Zeit darauf verwendet sich ein > wirklich gutes Software-Design zu überlegen. Sauberer Set und Getter sind auch ein gute Design nur halt ein andere Design.
Peter II schrieb: >> Wer seine Klassen per Default immer mit getter- und setter-Methoden >> ausstattet, der hat vermutlich kaum viel Zeit darauf verwendet sich ein >> wirklich gutes Software-Design zu überlegen. > Sauberer Set und Getter sind auch ein gute Design nur halt ein andere > Design. Damit führt man freilich die Datenkapselung ein Stück weit ad absurdum, denn man kann die Klasse intern nicht mehr so gut ändern.
Mark B. schrieb: > Damit führt man freilich die Datenkapselung ein Stück weit ad absurdum, > denn man kann die Klasse intern nicht mehr so gut ändern. warum sollte ich die Klasse dann nicht ändern können? Das Interface muss doch nur gleich bleiben?
Peter II schrieb: > warum sollte ich die Klasse dann nicht ändern können? Das Interface muss > doch nur gleich bleiben? Aber es wird ganz schwierig eine Klasse, die vorher ein "int getA() und void setA(int)" hatte, intern irgend wie anders zu implementieren, als mit einem int.
Peter II schrieb: > Mark B. schrieb: >> Damit führt man freilich die Datenkapselung ein Stück weit ad absurdum, >> denn man kann die Klasse intern nicht mehr so gut ändern. > > warum sollte ich die Klasse dann nicht ändern können? Das Interface muss > doch nur gleich bleiben? Das kann es aber nicht, wenn sich zum Beispiel der Datentyp ändert. Dann brauchst Du neue getter() und setter(), und musst sämtliche Stellen im Code ändern an denen die alten getter() und setter() Aufrufe standen.
Zum Thema gefällt mir sehr ein älterer Artikel von Herb Sutter (How Non-Member Functions Improve Encapsulation): http://www.drdobbs.com/cpp/how-non-member-functions-improve-encapsu/184401197
Vererbung heißt genaugenommen nicht "Erweitern" sondern "Spezialisieren" von Klassen. Deshalb: Wenn MyMotor sich verhält, wie ein allgemeiner Motor, dies aber auf spezielle Art und Weise erledigt, und nach außen wie ein beliebiger Motor aussehen soll, erbt er von Motor. Wenn MyMotor aber Funktionen von Motor nur benutzt, um andere oder Mehrwert-Funktionen zu realisieren, ist Komposition angesagt.
Uwe schrieb: > Vererbung heißt genaugenommen nicht "Erweitern" sondern > "Spezialisieren" von Klassen. Und eine Erweiterung ist eine Spezialisierung. Außerdem ist das was Du beschreibst eine Aggregation und keine Komposition. Daher: Daumen Runter. Eine Vererbung ist eine Art der Implementierung, es muss nicht gleich irgendwas sein wo die Basis als Schnittstelle verwendet wird. Eine Motorklasse die einfach mehr kann und nur den Allgemeinkram vom Basismotor übernimmt wird in C++ natürlich als Ableitung implementiert.
Ich bin mit C++ weniger am Controller unterwegs, sondern eher in größeren Frameworks. Dort kann ich dir sagen, das wir in solchen Situationen Vererbung möglichst nicht einsetzen oder nur unter Vorsichtsmaßnahmen. Das Problem dabei ist, das wenn eine Änderung in der Basis oder der abgeleiteten Klasse passiert es mit zunehmender Größe der Verflechtung schwierig wird, die Auswirkungen zu begreifen. In solchen Fällen wie du es hier beschreibst nutzten wir das Decorator-Pattern (s.a. https://de.wikipedia.org/wiki/Decorator) und kapseln die ursprüngliche Komponente vollkommen weg. Dann lässt es sich auch im Unittest besser greifen, da man dann die Möglichkeit hat, die Dekorierte Klasse gegen einen mock auszuwechseln und nur den Dekorierer zu testen.
Sven S. schrieb: > [..] Fällen wie du es hier beschreibst nutzten wir das Decorator-Pattern > (s.a. https://de.wikipedia.org/wiki/Decorator) und kapseln die > ursprüngliche Komponente vollkommen weg. Dann lässt es sich auch im Das kommt immer auf den Anwendungsfall an und wenn ihr bei so einem einfachen Konstrukt und bei dem verfügbaren Personal noch ein zweistufiges Schnittstellenklassensystem mit einer komplexen Arbeitsanweisung darüber legt, dann ist das eine Architekturschwäche.
Was Du willst ist ja keine Erweiterung des Motors, sondern eine darauf aufbauende Funktionalität. Dementsprechend wäre Variante b passender. Die Klasse sollte dann aber einen anderen Namen bekommen, z.B. Bewegung mit Methoden wie Bewegung::fahreGeradeaus(int geschwindigkeit)
Hallo zusammen! Tut mir leid, dass ich so lange nichts geantwortet habe! Ich bin im Krankenhaus auf der Kardiologoe gelandet und hatte keinen Rechner. Das durchchecken hat einige Tage gedauert. Ich werde mir eure Antworten in Ruhe durcharbeiten und im Zweifel noch mal nachfragen. Und, ja, melde mich nachher direkt an. Danke an alle
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.