Klasy - dziedziczenie

Autor podstrony: Krzysztof Zajączkowski

Stronę tą wyświetlono już: 4734 razy

Na stronie Programowanie → Podstawy Pythona → Klasy omawiałem podstawy dotyczące tworzenia klas w Pythonie, nadeszła stosowna ku temu pora, aby zacząć omawiać sam mechanizm dziedziczenia w Pythonie. Zanim jednak uczynię to z najdzikszą rozkoszą, warto poskładać do kupy utworzony na wcześniej przeze mnie wspomnianej stronie kod dwóch klas tam utworzonych:

class Matrix_tr: def __init__(self, m11 = 1, m12 = 0, m21 = 0, m22 = 1, dx = 0, dy = 0, alpha = None): if alpha is None: # if alpha angle is set on None value self.m11 = m11 self.m12 = m12 self.m21 = m21 self.m22 = m22 else: # in other case calculate m11 - m22 using alpha angle self.m11 = mt.cos(alpha) self.m12 = -mt.sin(alpha) self.m21 = - self.m12 # this should be sin of angle alpha self.m22 = self.m11 # this should be cos of angle alpha self.dx = dx # this is an offset for x self.dy = dy # this is an offset for y def __mul__(self, other): # multiplication operator (*) if isinstance(other, Point2D): # for object of Point2D class return Point2D(other.x * self.m11 + other.y * self.m12 + self.dx, other.x * self.m21 + other.y * self.m22 + self.dy) if isinstance(other, matrix_tr): # for object of matrix_tr class return matrix_tr(self.m11 * other.m11 + self.m12 * other.m21, self.m11 * other.m12 + self.m12 * other.m22, self.m21 * other.m11 + self.m22 * other.m21, self.m21 * other.m12 + self.m22 * other.m22, self.m11 * other.dx + self.m12 * other.dy + self.dx, self.m21 * other.dx + self.m22 * other.dy + self.dy) def __str__(self): return "| M11 = {m.m11:+{l}.5f} M12 = {m.m12:{l}.5f} dx = {m.dx:+{l}.5f} |\n| M21 = {m.m21:+{l}.5f} M22 = {m.m22:+{l}.5f} dy = {m.dy:+{l}.5f} |\n| M31 = {m31:+{l}.5f} M32 = {m32:+{l}.5f} {m33:+{l}.5f} |".format(m = self, l = 10, m31 = 0, m32 = 0, m33 = 1) class Point2D: tr = Matrix_tr() def __init__(self, x = None, y = None): self.x = float(input("Podaj współrzędną x: ")) if (x is None) else x self.y = float(input("Podaj współrzędną y: ")) if (y is None) else y def __del__(self): pass def __int__(self): return int((self.x * self.x + self.y * self.y) ** 0.5) def __float__(self): return (self.x * self.x + self.y * self.y) ** 0.5 def __str__(self): return "Point2D(x={x}, y={y})".format(x = self.x, y = self.y) def __eq__(self, other): if isinstance(other, Point2D): return True if other.x == self.x and other.y == self.y else False else: return True if (float(self) == other) else False def __ne__(self, other): return not (self == other) def __lt__(self, other): return float(self) < float(other) def __gt__(self, other): return float(self) > float(other) def __le__(self, other): return not (self > other) def __gt__(self, other): return not (self < other) def __add__(self, other): if isinstance(other, Point2D): return Point2D(self.x + other.x, self.y + other.y) else: return Point2D(self.x + float(other), self.y + float(other)) def __sub__(self, other): if isinstance(other, Point2D): return Point2D(self.x - other.x, self.y - other.y) else: return Point2D(self.x - float(other), self.y - float(other)) def __mul__(self, other): if isinstance(other, Point2D): return self.x * other.x + self.y * other.y else: return Point2D(self.x * float(other), self.y * float(other)) def __radd__(self, other): if isinstance(other, Point2D): return Point2D(self.x + other.x, self.y + other.y) else: return Point2D(self.x + float(other), self.y + float(other)) def __rsub__(self, other): if isinstance(other, Point2D): return Point2D(other.x - self.x, other.y - self.y) else: return Point2D(float(other) - self.x, float(other) - self.y) def __rmul__(self, other): if isinstance(other, Point2D): return self.x * other.x + self.y * other.y else: return Point2D(self.x * float(other), self.y * float(other)) def __iadd__(self, other): if isinstance(other, Point2D): self.x += other.x self.y += other.y else: self.x += float(other) self.y += float(other) return self def __isub__(self, other): if isinstance(other, Point2D): self.x -= other.x self.y -= other.y else: self.x -= float(other) self.y -= float(other) return self def __imul__(self, other): self.x *= float(other) self.y *= float(other) return self def __pos__(self): return Point2D(self.x, self.y) def __neg__(self): return Point2D(- self.x, - self.y) def __abs__(self): return Point2D(abs(self.x), abs(self.y)) # Metody klasy def det(self, pt): # calculate determinant of two vectors if isinstance(pt, Point2D): return self.x * pt.y - pt.x * self.y elif instance(pt, tuple): return self.x * pt[1] - pt[0] * self.y def draw(self): print(Point2D.tr * self)

Mechanizm dziedziczenia oraz wywoływanie konstruktora klasy bazowej

Utwórzmy sobie klasę o jakże wymownej nazwie Point3D. Ta klasa będzie dziedziczyła po klasie Point2D w sposób następujący:

class Point3D(Point2D): def __init__(self, x = None, y = None, z = None): Point2D.__init__(self, x, y) # constructor of base class self.z = float(input("Podaj współrzędną z: ")) if z is None else z

Można oczywiście dziedziczyć po wielu obiektach, wystarczy zaraz za nazwą klasy w nawiasie wypisać nazwy klas dziedziczonych oddzielone przecinkiem.

Wywoływanie metod klasy bazowej

Utwórzmy sobie taką oto metodę wewnętrzną klasy Point3D:

def draw(self): Point2D.draw(self) print(self)

Jeżeli teraz napiszę taki oto kod:

p3d = Point3D(1,2,3) p3d.draw() Point2D.draw(p3d)

W takim przypadku wyświetli się coś takiego:

Point2D(x=1, y=2)
Point3D(x=1, y=2, z=3)
Point2D(x=1, y=2)