|
5 | 5 | A class for representing shapes in the two-dimensional Euclidean plane.}%
|
6 | 6 | %
|
7 | 7 | \gitPython{\programmingWithPythonCodeRepo}{08_classes/circle.py}{--args format}{classes:circle}{%
|
8 |
| -A circle is a special shape, namely the set of all points whose distance from the center of the cirlce is exactly the radius.}% |
| 8 | +A circle is a special shape, namely the set of all points whose distance from the center of the circle is exactly the radius.}% |
| 9 | +% |
| 10 | +\gitPythonAndOutput{\programmingWithPythonCodeRepo}{08_classes}{circle_user.py}{--args format}{classes:circle_user}{% |
| 11 | +An example of using our class \pythonil{Circle} from \cref{lst:classes:circle}.}% |
9 | 12 | %
|
10 | 13 | \gitPython{\programmingWithPythonCodeRepo}{08_classes/polygon.py}{--args format}{classes:polygon}{%
|
11 | 14 | Polygons are special shapes delimited by straight lines between corner points.}%
|
|
16 | 19 | \gitPython{\programmingWithPythonCodeRepo}{08_classes/triangle.py}{--args format}{classes:triangle}{%
|
17 | 20 | A triangle is a polygon spanned by three points in a plane.}%
|
18 | 21 | %
|
| 22 | +We already learned that classes are a proper tool four grouping data and operations on the data together into one semantic unit. |
| 23 | +Classes also offer the concept of inheritance, which basically means \inQuotes{specialization}. |
| 24 | +Imagine that we would wanted to represent all geometrical shapes in a two-dimensional plance. |
| 25 | +Each shape has an associated area as well as a perimeter. |
| 26 | +We could create a class\pythonIdx{class} \pythonil{Shape} that provides two methods, \pythonil{area} and \pythonil{perimeter}, returning the area in in area units and the perimeter length in length units, respectively. |
| 27 | + |
| 28 | +A circle is a special shape. |
| 29 | +It does have a center as well as a radius. |
| 30 | +Knowing these two attributes, we can compute the area and perimeter. |
| 31 | +If we wanted to express this in terms of classes, we could say that the class\pythonIdx{class} \pythonil{Circle} is a special subclass of class~\pythonil{Shape}. |
| 32 | +It would have two attributes, \pythonil{center} (which could be an instance of \pythonil{Point}) and \pythonil{radius}, which would be a \pythonil{float}. |
| 33 | +The methods \pythonil{area} and \pythonil{perimeter} could then be implemented appropriately and use these attributes. |
| 34 | + |
| 35 | +This is already how inheritance works: |
| 36 | +If we want that a new class\pythonIdx{class}~\pythonil{Circle} inherits from a class\pythonIdx{class}~\pythonil{Shape}, all we have to do is to write \pythonil{class Circle(Shape):} instead of just \pythonil{class Circle:} when declaring the new circle class\pythonIdx{class}. |
| 37 | +Of course, we first need to create the class\pythonIdx{class}~\pythonil{Shape}. |
| 38 | + |
| 39 | +We do this in \cref{lst:classes:shape}. |
| 40 | +In this listing, we define \pythonil{Shape} as a new class\pythonIdx{class}. |
| 41 | +We want that this class has two methods, \pythonil{area} and \pythonil{perimeter}. |
| 42 | +The class\pythonIdx{class}~\pythonil{Shape} is not intended for being instantiated. |
| 43 | +Instead, we just want it to be the base class\pythonIdx{class} for \inQuotes{special} shapes. |
| 44 | +It does not have any attribute. |
| 45 | +Of course, we cannot really compute the area or the perimeter of such an abstract object. |
| 46 | +So both methods raise\pythonIdx{raise} an \pythonilIdx{NotImplementedError}. |
| 47 | +If someone would like to actually instantiate \pythonil{Shape} by doing, say, \pythonil{s = Shape()} and then invoke \pythonil{s.perimeter()}, this would fail. |
| 48 | + |
| 49 | +While \pythonil{Shape} itself is useless, it allows us to create different specialized subclasses that do implement \pythonil{area} and \pythonil{perimeter}. |
| 50 | +The user of these classes could then treat all of these different subclasses in the same way, because all of them support the interface defined by~\pythonil{Shape}. |
| 51 | + |
| 52 | +In \cref{lst:classes:circle}, we define the class\pythonIdx{class}~\pythonil{Circle}. |
| 53 | +By writing \pythonil{class Circle(Shape)}\pythonIdx{class}, we declare it as a subclass\pythonIdx{class} of \pythonil{Shape}. |
| 54 | +Its constructor \pythonilIdx{\_\_init\_\_}, we supply two parameters, \pythonil{center}, which is an instance of our class \pythonil{Point} from \cref{lst:classes:point}, and \pythonil{radius}, which can either be an \pythonil{int} or a \pythonil{float}. |
| 55 | +The constructor first checks if \pythonil{radius} is a finite and positive number. |
| 56 | +Otherwise, it raises\pythonIdx{raise} a \pythonilIdx{ValueError}. |
| 57 | +The constructor of the class\pythonIdx{class}~\pythonil{Point} already ensures that both coordinates of \pythonil{point} will be finite. |
| 58 | +This ensures that we indeed create valid circles. |
| 59 | +We store \pythonil{center} and \pythonil{radius} in two attributes of the same names. |
| 60 | +We annotate them with the \pgls{typeHint} \pythonilIdx{Final}, which means that they should not be changed after the object is constructed. |
| 61 | +We can now implement the function \pythonil{area} to return~$\numberPi\pythonil{radius}^2$ and \pythonil{perimeter} to return~$2\numberPi\pythonil{radius}$. |
| 62 | +With this, the complete interface defined by the superclass\pythonIdx{class}~\pythonil{Shape} is now filled with meaning. |
| 63 | + |
| 64 | +In \cref{lst:classes:circle_user}, we explore how this new class can be used. |
| 65 | +We create the new instance \pythonil{circ} of \pythonil{Circle} by providing the \pythonil{point=Point(2, 3)} and \pythonil{radius=4}. |
| 66 | +These parameters are indeed reflected by the corresponding attributes. |
| 67 | +We also confirm that \pythonil{isinstance(cir, Circle)}\pythonIdx{isinstance} is \pythonil{True}. |
| 68 | +It also holds that \pythonil{isinstance(cir, Shape)}\pythonIdx{isinstance}. |
| 69 | +Every instance of \pythonil{Circle} is also an instance of \pythonil{Shape}. |
| 70 | +Because \pythonil{Circle} is a special case of \pythonil{Shape}. |
| 71 | +% |
19 | 72 | \endhsection%
|
0 commit comments