280 likes | 449 Views
Computer Science 112. Fundamentals of Programming II Inheritance and Abstract Classes. Classification in the Animal Kingdom. animal. mammal. insect. bear. cat. dog. ant. cockroach. tick. classes. instances. Classification Among Artifacts: Vehicles. vehicle. car. bus. truck.
E N D
Computer Science 112 Fundamentals of Programming II Inheritance and Abstract Classes
Classification in the Animal Kingdom animal mammal insect bear cat dog ant cockroach tick classes instances
Classification Among Artifacts: Vehicles vehicle car bus truck sedan van suv pickup semi tow
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 Class object str list dict
Example: Python’s object Class object str list dict Array ArrayBag LinkedBag Counter 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 BagInterface LinkedBag ArrayBag ArraySortedBag 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?
Redundant Methods BagInterface ArrayBag ArraySortedBag The methods __init__, isEmpty, __len__, __str__, __eq__, __iter__, clear, and remove are exactly the same in ArrayBag and ArraySortedBag
Redundant Variables and Data BagInterface ArrayBag ArraySortedBag The variables DEFAULT_CAPACITY, self._size, and self._items are the same and refer to the same types of objects
Differences BagInterface ArrayBag ArraySortedBag The method __contains__ is an additional method in ArraySortedBag The method add works differently in ArraySortedBag The method __add__ creates an 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 BagInterface ArrayBag ArraySortedBag means implements an interface means is a subclass of another class
The New ArraySortedBag fromarraybagimportArrayBag classArraySortedBag(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) 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
The Method __contains__ fromarraybagimportArrayBag classArraySortedBag(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 instance variables self._items and self._size are visible within the ArraySortedBag class
The Method add fromarraybagimportArrayBag classArraySortedBag(ArrayBag): """An array-based sorted bag implementation.""" # Mutator methods defadd(self, item): """Adds item to self.""" # Empty or last item, call ArrayBag.add ifself.isEmpty() or \ item >= self._items[len(self) - 1]: ArrayBag.add(self, item) else: # Search for the first item >= new item 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 ArraySortedBag(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 The methods isEmpty, __len__, __str__, __add__, and __eq__ are exactly the same in ArrayBag and LinkedBag The variable self._size refers to the same type of data BagInterface LinkedBag ArrayBag ArraySortedBag
Redundant Code in the Bag Classes The methods isEmpty, __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 BagInterface LinkedBag ArrayBag Factor redundant data and methods up to a new parent class ArraySortedBag
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 AbstractBag AbstractList ArrayBag LinkedBag ArrayList LinkedList ArraySortedBag ArraySortedList Which methods are redundant?
Deeper Hierarchies c.isEmpty() len(c) str(c) c1 + (c2) c1 == c2 object AbstractCollection AbstractBag AbstractList ArrayBag LinkedBag ArrayList LinkedList ArraySortedBag ArraySortedList Which methods are the redundant ones?
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
AbstractCollection 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 ifsourceCollection: for item insourceCollection: self.add(item) 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)
For Friday Stacks Chapter 7