Klasy - dziedziczenie

Stronę tą wyświetlono już: 231 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:

Listing 1
  1. class Matrix_tr:
  2. def __init__(self, m11 = 1, m12 = 0, m21 = 0, m22 = 1, dx = 0, dy = 0, alpha = None):
  3. if alpha is None: # if alpha angle is set on None value
  4. self.m11 = m11
  5. self.m12 = m12
  6. self.m21 = m21
  7. self.m22 = m22
  8. else: # in other case calculate m11 - m22 using alpha angle
  9. self.m11 = mt.cos(alpha)
  10. self.m12 = -mt.sin(alpha)
  11. self.m21 = - self.m12 # this should be sin of angle alpha
  12. self.m22 = self.m11 # this should be cos of angle alpha
  13. self.dx = dx # this is an offset for x
  14. self.dy = dy # this is an offset for y
  15. def __mul__(self, other): # multiplication operator (*)
  16. if isinstance(other, Point2D): # for object of Point2D class
  17. return Point2D(other.x * self.m11 + other.y * self.m12 + self.dx, other.x * self.m21 + other.y * self.m22 + self.dy)
  18. if isinstance(other, matrix_tr): # for object of matrix_tr class
  19. 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)
  20. def __str__(self):
  21. 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)
  22. class Point2D:
  23. tr = Matrix_tr()
  24. def __init__(self, x = None, y = None):
  25. self.x = float(input("Podaj współrzędną x: ")) if (x is None) else x
  26. self.y = float(input("Podaj współrzędną y: ")) if (y is None) else y
  27. def __del__(self):
  28. pass
  29. def __int__(self):
  30. return int((self.x * self.x + self.y * self.y) ** 0.5)
  31. def __float__(self):
  32. return (self.x * self.x + self.y * self.y) ** 0.5
  33. def __str__(self):
  34. return "Point2D(x={x}, y={y})".format(x = self.x, y = self.y)
  35. def __eq__(self, other):
  36. if isinstance(other, Point2D):
  37. return True if other.x == self.x and other.y == self.y else False
  38. else:
  39. return True if (float(self) == other) else False
  40. def __ne__(self, other):
  41. return not (self == other)
  42. def __lt__(self, other):
  43. return float(self) < float(other)
  44. def __gt__(self, other):
  45. return float(self) > float(other)
  46. def __le__(self, other):
  47. return not (self > other)
  48. def __gt__(self, other):
  49. return not (self < other)
  50. def __add__(self, other):
  51. if isinstance(other, Point2D):
  52. return Point2D(self.x + other.x, self.y + other.y)
  53. else:
  54. return Point2D(self.x + float(other), self.y + float(other))
  55. def __sub__(self, other):
  56. if isinstance(other, Point2D):
  57. return Point2D(self.x - other.x, self.y - other.y)
  58. else:
  59. return Point2D(self.x - float(other), self.y - float(other))
  60. def __mul__(self, other):
  61. if isinstance(other, Point2D):
  62. return self.x * other.x + self.y * other.y
  63. else:
  64. return Point2D(self.x * float(other), self.y * float(other))
  65. def __radd__(self, other):
  66. if isinstance(other, Point2D):
  67. return Point2D(self.x + other.x, self.y + other.y)
  68. else:
  69. return Point2D(self.x + float(other), self.y + float(other))
  70. def __rsub__(self, other):
  71. if isinstance(other, Point2D):
  72. return Point2D(other.x - self.x, other.y - self.y)
  73. else:
  74. return Point2D(float(other) - self.x, float(other) - self.y)
  75. def __rmul__(self, other):
  76. if isinstance(other, Point2D):
  77. return self.x * other.x + self.y * other.y
  78. else:
  79. return Point2D(self.x * float(other), self.y * float(other))
  80. def __iadd__(self, other):
  81. if isinstance(other, Point2D):
  82. self.x += other.x
  83. self.y += other.y
  84. else:
  85. self.x += float(other)
  86. self.y += float(other)
  87. return self
  88. def __isub__(self, other):
  89. if isinstance(other, Point2D):
  90. self.x -= other.x
  91. self.y -= other.y
  92. else:
  93. self.x -= float(other)
  94. self.y -= float(other)
  95. return self
  96. def __imul__(self, other):
  97. self.x *= float(other)
  98. self.y *= float(other)
  99. return self
  100. def __pos__(self):
  101. return Point2D(self.x, self.y)
  102. def __neg__(self):
  103. return Point2D(- self.x, - self.y)
  104. def __abs__(self):
  105. return Point2D(abs(self.x), abs(self.y))
  106. # Metody klasy
  107. def det(self, pt): # calculate determinant of two vectors
  108. if isinstance(pt, Point2D):
  109. return self.x * pt.y - pt.x * self.y
  110. elif instance(pt, tuple):
  111. return self.x * pt[1] - pt[0] * self.y
  112. def draw(self):
  113. 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:

Listing 2
  1. class Point3D(Point2D):
  2. def __init__(self, x = None, y = None, z = None):
  3. Point2D.__init__(self, x, y) # constructor of base class
  4. 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:

Listing 3
  1. def draw(self):
  2. Point2D.draw(self)
  3. print(self)

Jeżeli teraz napiszę taki oto kod:

Listing 4
  1. p3d = Point3D(1,2,3)
  2. p3d.draw()
  3. 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)

Komentarze