computer science 112 fundamentals of programming ii inheritance and abstract classes
TRANSCRIPT
Classification in the Animal Kingdom
animal
mammal insect
bear cat dog ant cockroach tick
instances classes
Smokey Yogi Boo-Boo Spot Fido Billy Bob
Classification in Software
• Classes are organized in a hierarchy (subclasses and superclasses)
• Subclasses inherit the attributes (data) and behavior (methods) of superclasses
• We can eliminate redundant data and code by factoring them up the hierarchy
• We can get behavior for free by subclassing
Example: Python’s object Classobject
str list
Array CounterArrayBag LinkedBag
dict
object implements a default __eq__ and __str__
These methods already work for any subclass
These methods can be overridden in any subclass
Finding the Right Method
• When a method is run on an object, the PVM looks for its code in the object’s class
• If the code not found there, the PVM looks in the object’s superclass
• etc., until the code is not found in object, whereupon an exception is raised
Redundant Code in the Bag Classes
They all implement the same interface (same method headers)
Do any method implementations look the same?
Do any instance variables and their values look the same?
LinkedBag ArrayBag
BagInterface
ArraySortedBag
Redundant Methods
The methods __init__, isEmpty, __len__, __str__,
__eq__, __iter__, clear, and remove are
exactly the same in ArrayBag and ArraySortedBag
ArrayBag
BagInterface
ArraySortedBag
Redundant Variables and Data
The variables DEFAULT_CAPACITY, self._size, and self._items are the same and refer to the same types of objects
ArrayBag
BagInterface
ArraySortedBag
Differences
The method __contains__ is an additional method in ArraySortedBag
The method add works differently in ArraySortedBag
The method __add__ creates an ArraySortedBag
ArrayBag
BagInterface
ArraySortedBag
Inheritance to the Rescue!Make ArraySortedBag a subclass of ArrayBag
ArraySortedBag includes just the methods __init__, __contains__, and add
ArraySortedBag inherits all of the data and the other methods from ArrayBag
ArrayBag
BagInterface
ArraySortedBag
means implements an interface
means is a subclass of another class
from arraybag import ArrayBag
class ArraySortedBag(ArrayBag): """An array-based sorted bag implementation."""
# Constructor def __init__(self, sourceCollection = None): """Sets the initial state of self, which includes the contents of sourceCollection, if it's present.""" ArrayBag.__init__(self, sourceCollection)
The New ArraySortedBag
ArrayBag.__init__ calls the __init__ method in the parent class, which sets up the bag’s data
Note that self is passed as an additional argument
from arraybag import ArrayBag
class ArraySortedBag(ArrayBag): """An array-based sorted bag implementation."""
# Accessor methods def __contains__(self, item): """Returns True if item is in self or False otherwise.""" # Performs a binary search for item in the # self.items array
The Method __contains__
The instance variables self._items and self._size are visible within the ArraySortedBag class
from arraybag import ArrayBag
class ArraySortedBag(ArrayBag): """An array-based sorted bag implementation."""
# Mutator methods def add(self, item): """Adds item to self.""" # Empty or last item, call ArrayBag.add if self.isEmpty() or \ item >= self._items[len(self) - 1]: ArrayBag.add(self, item) else: # Search for the first item >= new item
The Method add
ArrayBag.add refers to the add method in the parent class, which adds the item to the logical end of the array
Generalizing the __add__ Method
class ArrayBag(object):
def __add__(self, other): """Returns a new bag containing the contents of self and other.""" result = ArrayBag(self) for item in other: result.add(item) return result
We really need a clone of self, whose type is the same as the type of self (not necessarily an ArrayBag)
Generalizing the __add__ Method
class ArrayBag(object):
def __add__(self, other): """Returns a new collection containing the contents of self and other.""" result = type(self)(self) for item in other: result.add(item) return result
The type function returns the type of a given object
This method will now work for any type of collection!
Redundant Code in the Bag Classes
LinkedBag ArrayBag
BagInterface
ArraySortedBag
The methodsisEmpty, __len__, __str__, __add__, and __eq__ are exactly the same in ArrayBag and LinkedBag
The variable self._size refers to the same type of data
Redundant Code in the Bag Classes
LinkedBag ArrayBag
BagInterface
ArraySortedBag
The methodsisEmpty, __len__, __str__, __add__, and __eq__ are exactly the same in ArrayBag and LinkedBag
The variable self._size refers to the same type of data
AbstractBag
Factor redundant data and methods up to a new parent class
Abstract and Concrete Classes
• An abstract class defines data and methods common to all subclasses, but is rarely instantiated
• A concrete class inherits some data and methods and defines other data and methods; this class is instantiated
Leverage Abstraction
• __str__, __add__, __eq__, and isEmpty just call other methods to get their work done
• Try to use just method calls in your code; avoid direct references to instance variables as much as possible
• Such code will be more general and easier to push up in the hierarchy
Deeper Hierarchies
object
ArrayBag LinkedBag
AbstractBag
ArrayList LinkedList
AbstractList
Which methods are redundant?
ArraySortedBag ArraySortedList
Deeper Hierarchies
object
ArrayBag LinkedBag
AbstractBag
AbstractCollection
ArrayList LinkedList
AbstractList
Which methods are the redundant ones?
ArraySortedBag ArraySortedList
c.isEmpty()len(c) str(c) c1 + (c2)c1 == c2
AbstractCollection
• Includes data and behavior for any type of collection
• Maintains the logical size (len and isEmpty)
• Copies elements during instantiation
• Provides default implementations of the +, ==, and str operations
class AbstractCollection(object): """An abstract collection implementation."""
# Constructor def __init__(self, sourceCollection = None): """Sets the initial state of self, which includes the contents of sourceCollection, if it's present.""" self._size = 0 if sourceCollection: for item in sourceCollection: self.add(item)
AbstractCollection
Also defines the methods isEmpty, __len__, __str__, __add__, and __eq__
Using Inheritance
• Sometimes you’ll spot an opportunity to subclass under another class immediately (the GUI classes are good examples of this)
• Most of the time, you’ll develop a bunch of classes and realize only later that they have redundancies that can be factored into common superclasses (refactoring)
The Complete Collection Hierarchy