INTERFACES

Fred Agbo

2025-09-29

Announcements

  • Welcome to week 6!
  • Week 5 assignment (Problem set 2) will be due on Wednesday at 10pm

Learning Objectives

  • Develop an interface for a given collection type
  • Implement multiple classes that conform to the interface of a collection type
  • Assess the tradeoffs in running time and memory usage of multiple implementations of a given collection type
  • Implement a basic iterator

Developing an Interface

  • An interface defines a set of methods and behaviors that a class must implement, without specifying how these methods are implemented.
  • When you run Python’s help function to obtain information about a module, data type, method, or function,
    • You are accessing documentation about that resource’s interface
  • Interfaces are concise and informative:
    • They allow you to grasp the behavior of a resource
  • In this section, you will develop the interface for a simple collection type called a bag:
    • A bag interface allows clients to use bags effectively and allows implementers to produce new classes that implement this interface

Designing the Bag Interface

  • Derive an interface from thinking about what bags can do in a real-world situation:
    • A bag can contain any objects
  • You will want to know the following:
    • How many things are in a bag
    • How to add things to it or remove them from it
    • Whether a bag is empty
    • How to empty a bag in a single operation
    • How to determine whether a given item is in a bag
    • How to view each item in a bag without emptying it
    • How to create a bag

Designing the Bag Interface

  • The next step is to draw up a list of function names, method names, and operator symbols that meet the descriptions of these operations

  • Examples include:

      - add
      - clear
      - count
      - for ...
      - in
      - isEmpty
      - len
      - remove
      - str
      - +
      - ==

Specifying Arguments and Return Values

  • Next, add arguments to the operations in the interface
    • And think about what values, if any, they return
  • Below, variables b and c refer to bags
b.clear()                   # Make the bag empty
for item in range(10):      # Add 10 numbers to it
    b.add(item)
print(b)                    # Print the contents (a string)
print(4 in b)               # Is 4 in the bag?
print(b.count(2))           # 1 instance of 2 in the bag
c = b + b                   # Contents replicated in a new bag
print(len(c))               # 20 numbers
for item in c:              # Print them all individually
    print(item)
for item in range(10):      # Remove half of them
    c.remove(item)
print(c == b)               #Should be the same contents now

Arguments for Bag Operations and Their Methods

User’s Bag Operation Method in a Bag Class
b = () init(self, sourceCollection=None)
b.add(item) add(self, item)
b.clear() clear(self)
b.count(item) count(self, item)
b.isEmpty() isEmpty(self)
b.remove(item) remove(self, item)
len(b) __len__(self)
str(b) __str__(self)
for item in b __iter__(self).
item in b __contains__(self, item) Not needed if __iter__ is included
b1 + b2 __add__(self, other)
b == anyObject __eq__(self, other)

Constructors and Implementing Classes

  • The first row in table above shows an operation that is the constructor for the particular type of bag being created
  • The syntactic form <class name> is used in the table to indicate that this can be the name of any implementing bag class:
    • The method in the right column is always named _init_
  • An example of code segment that creates an empty linked bag and an array bag that contains the numbers in a given list is as shown:
from arraybag import ArrayBag
from linkedbag import LinkedBag
 
bag1 = LinkedBag()
bag2 = ArrayBag([20, 60, 100, 43])

Constructors and Implementing Classes

  • Final step before expressing an interface in code:
    • describe clearly and concisely what each method does
    • include not only what you expect to occur under normal conditions but also what will happen when something abnormal, such as an error, occurs
  • A more detailed form of documentation can include preconditions and postconditions:
    • Precondition is a statement of what must be true for a method to perform its actions correctly
    • Postcondition states what will be true after the method completes execution, assuming that its preconditions are also true:
      • Usually included in mutator methods, which modify the internal state of an object

Exceptions and Documentation

  • Documentation in an interface should include a statement of any exceptions that could be raised:
    • Example, a bag’s remove method might raise a KeyError if the target item is not in the bag
  • A Python method header for the remove method:
def remove(self, item):
"""Precondition: item is in self.
Raises: KeyError if item in  not in self.
   Postcondition: item is removed from self."""

Coding an Interface in Python

  • To create an interface, list each of the method headers with its documentation and complete each method with a single pass or return statement:
    • A pass statement is used in the mutator methods that return no value, whereas each accessor method returns a simple default value, such as False, 0, or None
  • So method headers can be checked with the compiler
    • You may place them within a class whose suffix is “Interface”

BagInterface in Python

"""
File: baginterface.py
Author: Ken Lambert
"""
 
class BagInterface(object):
    """Interface for all bag types."""
 
    # Constructor
    def __init__(self, sourceCollection = None):
        """Sets the initial state of self, which includes the
        contents of sourceCollection, if it’s present."""
        pass
 
    # Accessor methods
    def isEmpty(self):
        """Returns True if len(self) == 0,
        or False otherwise."""
        return True
 
    def __len__(self):
        """Returns the number of items in self."""
        return 0
 
    def __str__(self):
        """Returns the string representation of self."""
        return ""
 
    def __iter__(self):
        """Supports iteration over a view of self."""
        return None
    def __add__(self, other):
        """Returns a new bag containing the contents
        of self and other."""
        return None
 
    def __eq__(self, other):
        """Returns True if self equals other,
        or False otherwise."""
        return False
     
    def count(self, item):
        """Returns the number of instances of item in self."""
        return 0
 
    # Mutator methods
    def clear(self):
        """Makes self become empty."""
        pass
 
    def add(self, item):
        """Adds item to self."""
        pass
 
    def remove(self, item):
        """Precondition: item is in self.
        Raises: KeyError if item in not in self.
        Postcondition: item is removed from self."""
        pass