Eigene Klassen¶
Häufig ist es sinnvoll eigene Klassen/Datentypen zu erstellen, bei Programmen mit einer GUI ist es fast unerlässlich.
Definition¶
Die Klasse ist also der Bauplan, aus dem ‚konkrete‘ Objekte (Instanzen) erstellt werden. Klassennamen beginnen vereinbarungsgemäß mit einem Groß-Buchstaben !
Wir beginnen mit der leeren Hülle einer Klasse:
(die Anweisung pass „macht nichts“, es geht nur um die Syntax/Sprachregeln,
da ja nach dem ‚:‘ etwas Eingerücktes stehen muss.)
class Tier():
pass
# Der leere Bauplan genügt schon, um daraus Objekte erzeugen zu können.
elch = Tier()
Methoden und Instanzvariablen¶
Jetzt wollen wir die Klasse mit etwas Inhalt füllen und erstellen eine Methode. Eine Methode ist eine spezielle Art von Funktion, die nur zusammen mit einem Objekt dieser Klasse verwendet werden kann.
Methoden haben in ihrer Parameterliste immer als erstes ein self stehen.
Beim Aufruf fehlt dieser Parameter, d.h. der Aufruf hat immer ein Argument
weniger als es Parameter in der Definition der Methode gibt.
class Tier():
def sprich(self):
print("Hallo")
elch = Tier()
elch.sprich()
Die Dinge, die bei jedem einzelnen Objekt einen eigenen Wert haben können, werden in Attributen, oder besser Instanzvariablen gespeichert.
Zu erkennen sind Instanz-Variablen daran, dass sie mit einem self beginnen.
Sie haben den großen Vorteil, dass sie in allen anderen Methoden derselben Klasse
einfach weiterverwendet werden können.
class Tier():
def setfutter(self, futter):
# eine Instanzvariable definieren
self.futter = futter
def sprich(self):
# die Instanzvariable kann hier verwendet werden !!!
print("Ich mag", self.futter)
elch = Tier()
elch.setfutter("Kräuter")
elch.sprich()
Konstruktor¶
Allerdings gibt es bei diesem Programm noch ein Problem, denn
was passiert, wenn wir die Methode sprich() verwenden, bevor wir
die Methode setfutter() aufgerufen haben?
Es gibt einen Fehler, denn die Instanzvariable self.futter wurde noch nicht definiert,
der entsprechende Programmcode wurde noch nicht durchlaufen.
Dass läßt sich aber leicht vermeiden, denn wie bei allen objektorientierten Sprachen, gibt es die Möglichkeit ein Objekt zu initialisieren. Ein solche Methode wird (in allen Objekt-orientierten-Sprachen) als Konstruktor bezeichnet.
Wenn also in einer Klasse eine Methode mit dem dem festgelegten Namen __init__(...)
definiert wurde (jeweils zwei Unterstriche), dann wird diese Methode einmal
beim Erstellen eines jeden Objekts ausgeführt.
Das ist der richtige Ort, um den Instanzvariablen einen Anfangswert zu geben, sie also zu initialisieren.
Ich würde also grundsätzlich empfehlen, alle Instanzvariablen schon im Konstruktor anzulegen.
class Tier():
def __init__(self):
print("Konstruktor Tier")
# Instanzvariablen initialisieren
self.futter = "alles"
self.gewicht = None
def
...
elch = Tier()
elch.sprich()
Das Schlüsselwort None bedeutet, dass der Wert noch nicht festgelegt ist.
Die Instanzvariable self.gewicht ist damit definiert und kann verwendet werden
ohne dass das Programm abstürzt.
Der Konstruktor kann auch Parameter haben und damit lässt sich sicherstellen, dass z.B. für jedes Tier eine Tierart festgelegt werden muss (=mandatory).
class Tier():
def __init__(self, art):
print("Konstruktor Tier:", art)
self.art = art
self.futter = "alles"
def sprich(self):
print("Ich bin ein ", self.art, "und mag gerne", self.futter)
tier = Tier("Elch")
tier.sprich()
Namensraum¶
Setter- und Getter-Methoden sind die klassische Art um den Wert von Instanzvariablen zu setzen oder zu ermitteln. Natürlich könnten die Methodennamen auch anders heißen, aber set…() und get…() haben sich eingebürgert.
class Tier():
def __init__(self):
self.futter = "alles"
def setfutter(self, futter):
self.futter = futter
def getfutter(self):
return self.futter
elch = Tier()
elch.setfutter("Kräuter")
myfood = elch.getfutter()
print("und mag", myfood)
In vielen Objektorientierten Sprachen, kann auf einzelne Objekte nur über Methoden zugegriffen werden, in Python ist es aber auch direkt über den Objektnamen möglich. Das Objekt bildet dabei sozusagen einen eigenen Namensraum.
In diesem Beispiel könnte ich das Futter also auch direkt verwenden:
elch = Tier()
elch.setfutter("Kräuter")
print("Ich mag", elch.futter)
Methoden¶
Soll innerhalb einer Methode eine andere Methode der gleichen Klasse aufgerufen werden, geschieht das in der üblichen Weise, links vom Punkt das Objekt und rechts die Methode:
class Tier():
def __init__(self, art):
self.art = art
self.futter = "alles"
def sprich(self):
print("Ich bin ein ", self.art, "und mag gerne", self.futter)
def setfutter(self,futter):
self.futter = futter
# ==> Um eine Methode aus der eigenen Klasse aufzurufen,
# wird vor den Namen der Methode das 'self' gestellt !
self.sprich()
tier = Tier("Elch")
tier.sprich()