The Position Interface: Protecting Node!
The Node
class represents a "position" in a linked list. We can further abstract the idea of a position. For example, we can create the following interface:
/**
* Generic position interface.
*
* @param <T> the element type.
*/
public interface Position<T> {
/**
* Read element from this position.
*
* @return element at this position.
*/
T get();
}
Then, we can have the Node
class to implement this interface:
public class DoublyLinkedList<T> {
private Node<T> head;
private Node<T> tail;
private static class Node<E> implements Position<E> {
E data;
Node<E> next;
Node<E> prev;
Node(E data) {
this.data = data;
}
@Override
public E get() {
return data;
}
}
// Constructor not shown
public Position<T> addFirst (T data) { }
public Position<T> addLast(T data) { }
public Position<T> get(int index) { }
public void delete(Position<T> target) { }
public void insertAfter(Position<T> target, T data) { }
public void insertBefore(Position<T> target, T data) { }
}
Notice how a client of DoublyLinkedList
works with values of type Position
but internally, the DoublyLinkedList
, operates on Node
, the subtype of Position
.
Exercise How does this strategy "protect" Node
?
Solution
A client who receives a value of type Position
have one operation at their disposal: get
, which returns the data stored at that position. However, they will not directly access data
or next
/prev
reference variables.