(2021.06.04 Fri)
Hierarchy
A natural way to organise various structural components of a software package is in a hierachical fashion, with similar abstract definitions grouped together in a level-by-level manner that goes from specific to more general as one traverses up the hierarchy. Using mathematical notations, the set of a houses is a subset of the set of buildings, but a superset of the set of ranches.
Two ways to differentiate subclass from superclass: Specialise and extend
A subclass may specialise an existing behavior by providing a new implementatoin that overrides an existing method. A subclass may also extend its superclass by providing brand new methods.
Case: CreditClass
CreditCard class and subclass PredatorCreditClass.
PredatorCreditClass starts with the syntax class PredatorCreditClass(CreditClass)
. The mechanism for calling the inherited constructor relies on the syntax, super()
, i.e.,
super().__init__(customer, bank, acnt, limit)
class PredatorCreditClass(CreditClass):
"""An extension to CreditClass that compounds interest and fees."""
def __init__(self, customer, bank, acnt, limit, apr):
"""Create a new predatory credit card intant
...
"""
super().__init__(customer, bank, acnt, limit) # 调用变量没有self
self._apr = apr
def charge(self, price):
"""Overrides CreditClass.charge
...
"""
success = super().charge(price) # super() 可当成base class的instance
if not success:
self._balance += 5
return success
def process_month(self):
"""extend."""
if self._balance > 0:
monthly_factor = pow(1 + self._apr, 1/12)
self._balance *= monthly_factor
Case: Hierarchy of Numeric Progressions
Progression base class
class Progression:
"""pass"""
def __init__(self, start=0):
"""Initialise current to the first value of the progression."""
self._current = start
def _advance(self):
"""pass"""
self._current += 1
def __next__(self):
"""overload magic method"""
if self._current is None:
raise StopIteration()
else:
answer = self._current
self._advance()
return answer
def __iter__(self):
"""By convention, an iterator must return itself as an iterator."""
return self
def print_progression(self, n):
"""Pass"""
print(' '.join(str(next(self)) for j in range(n)))
Arithmetic Progression Class
class ArithmeticProgression(Progression):
"""Iterator producing an arithmetic progression."""
def __init__(self, increment=1, start=0):
"""Create a new arithmetic progression."""
super().__init__(start)
self._increment = increment
def _advance(self):
"""Update current value by adding the fixed increment."""
self._current += self._increment
Geometric Progression Class
class GeometricProgression(Progression):
"""Iterator producing a geometric progression."""
def __init__(self, base=2, start=1):
"""Create a new geometric progression."""
super().__init__(sart)
self._base = base
def _advance(self):
"""Update current value by multiplying i by the base value."""
self._current *= self._base
Fibonacci Progression Class
class FibonacciProgression(Progression):
"""Iterator producing a generalised Fibonacci progression."""
def __init__(self, first=0, second=1):
"""..."""
super().__init__(first)
self._prev = second -first
def _advance(self):
"""..."""
self._prev, self._current = self._current, self._prev + self._current
Abstract Base Class (ABC)
Class Progression above is an ABC, avoiding repetition of code. In Progression case, the real purpose is to centralise the implementations of behaviors that other progressions needed, thereby streamlining the code that is relegated to those subclasses.
The Progression class serves as a base class through inheritance. More formally, an abstract base class is one that cannot be directly instantiated, while a concrete class is one that can be instantiated. By this definition, Progression calss is technically concrete, although we essentially designed it as an abstract base class.
In statically typed languages such as Java and C++, an abstract base class serves as a fomal type that can guarantee one or more abstract methods. This provides support for polymorphism, as a variable may have an abstract base class as its declared type, even though it refers to an instance of a concrete subclass. Because there are no declared types in Python, this kind of polymorphism can be accomplished without the need for a unifying abstract abse class. For this reason, there is not as strong a tradition of defining abstract base classes in Python, although Python's abc
module provides support for defining a formal abstract base class. (Python传统上不需要ABC)
Reference
1 M. T. Goodrich and etc, Data Structures & Algorithms in Python.