Klassen erweitern – Vererbung

In der Physik sind häufig Vierer–Vektoren (=Lorentz–Vektor) gefragt, d.h. Dreier–Vektoren erweitert um Zeit bzw. Energie–Komponente. Mögliche LorentzVektor Klasse:

class LorentzVec(object):
    "Class for 4 Vector and operations"
    def __init__( self, t=0., x=0., y=0., z=0.):
        self.x = x
        self.y = y
        self.z = z
        self.t = t
    def Add( self, lv ):
        newvec = LorentzVec( self.t+lv.t, self.x+lv.x, self.y+lv.y, self.z+lv.z)
        return newvec
    def Angle( self, lv ):
        ...
    def Mass( self ):
        ...

Viele Gemeinsamkeiten mit ThreeVec und ein paar Erweiterungen

Design Prinzip Code-Reuse statt cut&paste !

\bgroup\color{dgreen}\ensuremath{\color{dgreen}{\Rightarrow}}\egroup LorentzVector enthält ThreeVector: "has-a" relationship (Aggregation).


class LorentzVec(object):
    "Class for 4 Vector and operations"
    def __init__( self, t=0., x=0., y=0., z=0.):
        self.v3 = ThreeVector( x, y, z )  # contains ThreeVector
        self.t = t
    def Add( self, tv ):
        w = self.v3 + tv.v3 # add ThreeVectors first
        newvec = LorentzVec( self.t+tv.t,  w.x, w.y, w.z)
        return newvec
    def Angle( self, tv ):
        return( self.v3.Angle( tv.v3) # use ThreeVector Method
    def Mass( self ):
        ...

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 ....


class LorentzVec(ThreeVec): # inherits from ThreeVec
    "Class for 4 Vector and operations"
    def __init__( self, t=0., x=0., y=0., z=0.):
        ThreeVec.__init__( self, x, y, z )  # initialize  ThreeVec
        self.t = t
    def Add( self, tv ):
        w = ThreeVec.Add( self, tv ) # call ThreeVec method first
        newvec = LorentzVec(  self.t+tv.t, w.x, w.y, w.z)
        return newvec
#    def Angle( self, tv ): no need to define here, available from ThreeVec
    def Mass( self ):
        ...

Jetzt übernimmt bzw. erbt LorentzVector alle Funktionen von ThreeVec, z.B. Winkelberechnung funktioniert sofort:
  c = LorentzVec(1.000001,1.,0.,0.)
  d = LorentzVec(2.,1.,1.,0.)
  c.Angle(d)


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.



Rechteck und Quadrat
Zunächst naheliegend Quadrat von Rechteck  abzuleiten (=vererben), viele Funktionen und Eigenschaften gemeinsam. Aber grundsätzliche Probleme bei Verhalten, z.B.:


class Rechteck:
    def __init__( self, w, l ):
        self.w = w
        self.l = l
  // ...
  def setLength( self, len):
      ...
  def setWidth( self, wid):
      ...
};

Was soll ein Quadrat mit diesen Funktionen machen ?

setLength(..) bei Quadrat ändert immer auch width und vice-versa. Verhalten nicht kompatibel mit Rechteck .

Wichtig für OO Programmieren ist konsistentes Verhalten von Klassen, dazu wird Vererbung eingesetzt. Es geht weniger um bequemes Übernehmen von Funktionalität.

Mathematisch ist Quadrat Unterklasse von Rechteck, aber nicht im Sinne von OOP !