Inheritance and Defining Subclasses

 

Python

Java

 

In an object-oriented programming language, one can define a new class that reuses code in another class.  The new class becomes a sublclass of the existing class, which is also called its parent class.  The subclass inherits all of the attributes, including methods and variables, from its parent class and from any ancestor classes in the hierarchy.

 

Subclassing is a convenient way to provide extra or more specialized functionality to an existing resource.  For example, a queue guarantees access to its elements in first-in, first-out order.  A priority queue behaves in most respects just like a queue, except that the higher priority elements are removed first.  If elements have equal priority, they are removed in standard FIFO order.  A priority queue is thus a subclass of queue, with a specialized method for insertions that guarantees the appropriate ordering of elements.  The priority queue obtains all of its other methods from the queue class for free.

 

 

Here is the definition of a LinkedQueue class for ordinary queues: 

 

 

class OneWayNode:

 

    def __init__(self, data, next):

        self.data = data

        self.next = next

 

class LinkedQueue:

 

    def __init__(self):

        self.front = self.rear = None

        self.size = 0

 

    def enqueue(self, element):

        n = OneWayNode(element, None)

        if self.isEmpty():

            self.rear = self.front = n

        else:

            self.rear.next = n

            self.rear = n

        self.size += 1

 

    def dequeue(self):

        element = self.front.data

        self.front = self.front.next

        self.size -= 1

        if self.isEmpty():

            self.rear = None

        return element

 

    def peek(self):

        return self.front.data

 

    def isEmpty(self):

        return len(self) == 0

 

    def __len__(self):

        return self.size

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

The form for defining a subclass is

 

class <subclass name>(<parent class name>):

 

    <variables and methods>

 

The LinkedPriorityQueue class is a subclass of LinkedQueue.  The new class includes just two methods, __init__ and enqueue.  The __init__ method in LinkedPriorityQueue simply calls the same method in its parent class, using the form

 

<parent class name>.__init__(self)

 

This causes the parent class to initialize its instance variables.

 

The new enqueue method first checks for an empty queue and if that is true, calls the enqueue method in the parent class using the form

 

<parent class name>.<method name>(<args>)

 

Otherwise, the method searches for the appropriate position of the new element and inserts it there.  Because the front of the queue is at the head of the linked structure, the search stops when the incoming element is strictly less than element in the queue.  Thus, an incoming element is placed behind all elements of equal priority.

 

 

 

 

 

Here is the definition of LinkedPriorityQueue:  

 

class LinkedPriorityQueue(LinkedQueue):

 

    def __init__(self):

        LinkedQueue.__init__(self)

 

    def enqueue(self, element):

        if self.isEmpty():

            LinkedQueue.enqueue(self, element)

        else:

            probe = self.front

            while probe != None and element >= probe.data:

                trailer = probe

                probe = probe.next

            if probe == None:            # At rear of queue

                self.rear.next = OneWayNode(element, None)

                self.rear = self.rear.next

            elif probe == self.front:    # At front of queue

                self.front = Node(element, self.front.next)

            else:                        # Betwixt two nodes

                trailer.next = Node(element, probe)

            self.size += 1

 

 

In an object-oriented programming language, one can define a new class that reuses code in another class.  The new class becomes a sublclass of the existing class, which is also called its parent class.  The subclass inherits all of the attributes, including methods and variables, provided they are specified as public or protected, from its parent class and from any ancestor classes in the hierarchy.

 

Subclassing is a convenient way to provide extra or more specialized functionality to an existing resource.  For example, a queue guarantees access to its elements in first-in, first-out order.  A priority queue behaves in most respects just like a queue, except that the higher priority elements are removed first.  If elements have equal priority, they are removed in standard FIFO order.  A priority queue is thus a subclass of queue, with a specialized method for insertions that guarantees the appropriate ordering of elements.  The priority queue obtains all of its other methods from the queue class for free.

 

The LinkedQueue class makes its instance variables visible to subclasses but not to others by declaring them as protected.  Likewise, the inner OneWayNode class and its attributes are also defined as protected.

 

Here is the definition of a LinkedQueue class for ordinary queues:

 

import java.util.*;

 

public class LinkedQueue<E> implements TrueQueue<E>{

 

    protected OneWayNode<E> front, rear;

    Protected int size;

 

    public LinkedQueue(){

      this.front = this.rear = null;

      this.size = 0;

    }

 

    public void enqueue(E element){

        OneWayNode<E> n = OneWayNode<E>(element, null);

        if (this.isEmpty())

            this.rear = this.front = n;

        else{

            this.rear.next = n;

            this.rear = n;

        }

        this.size += 1;

    }

 

    public E dequeue(){

        E element = this.front.data;

        this.front = this.front.next;

        this.size -= 1;

        if (this.isEmpty())

            this.rear = null;

        return element;

    }

 

    public E peek(){;

      return this.front.data;

    }

 

    public boolean isEmpty(){

      return this.size() == 0;

    }

 

    public int size(){

      return this.size == 0;

    }

 

    protected class OneWayNode<E>{

 

        protected E data;

        protected OneWayNode<E> next;

 

        protected OneWayNode(E data, OneWayNode next){

            this.data = data;

            this.next = next;

        }

    }

}

 

 

The form for defining a subclass is

 

public class <subclass name> extends <parent class name>{

 

    <variables and methods>

}

 

The LinkedPriorityQueue class is a subclass of LinkedQueue.  The new class includes a constructor and the enqueue method.  The constructor in LinkedPriorityQueue is optional, but explicitly calls the constructor in its parent class, using the statement

 

super();

 

This causes the parent class to initialize its instance variables.

 

The new enqueue method first checks for an empty queue and if that is true, calls the enqueue method in the parent class using the form

 

super.<method name>(<args>)

 

Otherwise, the method searches for the appropriate position of the new element and inserts it there.  Because the front of the queue is at the head of the linked structure, the search stops only when the incoming element is strictly less than element in the queue.  Thus, an incoming element is placed behind all elements of equal priority. 

 

Elements in a priority queue must be comparable.  Therefore, the element type of the LinkedPriorityQueue class is specified as Comparable.  The syntax for relating the element types of LinkedPriorityQueue and LinkedQueue in the class header is a bit tricky, but gets the job done.

 

Here is the definition of LinkedPriorityQueue:  

 

import java.util.*;

 

public class LinkedPriorityQueue<E extends Comparable>

                                extends LinkedQueue<E>{

 

    public LinkedPriorityQueue(){

       super();

    }

 

    public void enqueue(E element){

       if (this.isEmpty())

           super.enqueue(element);

        else{

            OneWayNode<E> probe = this.front;

            OneWayNode<E> trailer = null;

            while (true){

                if (probe == null ||

                    element.compareTo(probe.data) < 0)

                    break;

                trailer = probe;

                probe = probe.next;

            }

            if (probe == null)                   # At rear of queue

                this.rear.next = new OneWayNode<E>(element, null);

                this.rear = this.rear.next;

            else if (probe == this.front)        # At front of queue

                this.front = new OneWayNode<E>(element, this.front.next);

            else                                 # Betwixt two nodes

                trailer.next = new OneWayNode<E>(element, probe);

            this.size += 1;

        }

    }

}

 

 

 

Previous

Index

Next