class MyLVector { private: // coordinates, hidden double t; double x; double y; double z; public: MyLVector();// The default constructor MyLVector(double c0, double c1, double c2, double c3);// Other constructor // methods: double Length(); // get length of vector double T(); double X(); double Y(); double Z(); MyLVector Add( MyLVector p ) ; // add two vectors double Angle( MyLVector p ); // angle between two vectors double Mass() ; // get mass of 4-vector };
Design Prinzip Code-Reuse statt cut&paste !
class MyLVector { private: // coordinates, hidden double t; My3Vector vec3; // My3Vector as private member public: MyLVector();// The default constructor MyLVector(double c0, double c1, double c2, double c3);// Other constructor // methods: double Length(); // get length of vector double T(); double X(); double Y(); double Z(); MyLVector Add( MyLVector p ); // add two vectors double Angle( MyLVector p ); // angle between two vectors // .... };
LorentzVektor enthält DreierVektor:
"has-a" relationship
(Aggregation).
// implementation // Constructor MyLVector::MyLVector(double c0, double c1, double c2, double c3) : vec3(c1, c2, c3), t(c0) // special initialization syntax {} double MyLVector::Angle( MyLVector p ) { return( vec3.Angle(p.vec3)); // re-use code } double MyLVector::X() { return( vec3.X() ); // re-use code }
Im Prinzip ok, allerdings viele stumpfsinnige Mapping–Funktionen von DreierVektor auf ViererVektor nötig.
3. Möglichkeit: Vererbung
ViererVektor ist DreierVektor mit ein paar Ergänzungen ....
#include "My3Vector.h" // My3Vector declarations class MyLVector : public My3Vector { // inherit from My3Vector private: double t; public: MyLVector();// The default constructor MyLVector(double c0, double c1, double c2, double c3);// Other constructor // methods: double Mass(); // get mass of 4-vector double Mass( MyLVector p); // get mass of two 4-vector }; // implementation MyLVector::MyLVector(double c0, double c1, double c2, double c3) : My3Vector(c1, c2, c3), t(c0) // special initialization syntax {} double MyLVector::Mass() // Method for mass: { // caution: direct access to My3Vector x,y,z doesn't work with private ! return( sqrt( t*t - x*x - y*y - z*z ) ); }
Jetzt übernimmt bzw.
erbt
MyLVector alle Funktionen
von
My3Vector, z.B. Winkelberechnung funktioniert sofort:
MyLVector c(1.000001,1.,0.,0.), d(2.,1.,1.,0.);
c.Angle(d);
Falls Methode geändert werden muss, z.B. MyLVector::Add, entsprechend neu implementieren, bei c.Add(d) wird dann die MyLVector Version benutzt.
Vererbung ( "is-a" relationship) bedeutet alle Eigenschaften und Funktionen einer Grund-Klasse ( base class) in eine weitere Klasse ( derived class) zu übernehmen. Daraus ergibt sich eine enorme Erweiterung der Funktionalität. Ausgehend von vorhandenen, simplen Grundklassen können relativ leicht neue Klassen abgeleitet werden, ohne jedesmal diesselben grundlegenden Funktionen neu zu implementieren.
Allerdings: Vererbung nicht übertreiben, nicht immer sinnvoll, im Zweifelsfall Aggregation verwenden.
Bei Verwendung von Polymorphismus (nächster Kurs ...) ist vor allem konsistentes Verhalten wichtig bei Vererbung, weniger die Funktionalität.
Abhilfe: Weiterer Modifier protected, im Prinzip analog zu private, d.h. kein Zugriff von ausserhalb der Klasse, jedoch mit Ausnahme von abgeleiteten Klassen.