下面是我正在使用的一本教科书中的一个类。一切对我来说都是有意义的,除了我应该如何使用任何接受IPosition的函数作为参数EX: before()和addBefore()函数
如果IPosition是在私有嵌套节点类中实现的接口,我如何使用这些函数,例如,我想在100项列表中使用addBefore()函数添加一些新数据?
public class LinkedPositionalList <E> implements IPositionalList<E>{
private static class Node<E> implements IPosition<E> {
private E element; // reference to the element stored at this node
private Node<E> prev; // reference to the previous node in the list
private Node<E> next; // reference to the subsequent node in the list
public Node(E e, Node<E> p, Node<E> n) {
element = e;
prev = p;
next = n;
}
public E getElement() throws IllegalStateException {
if (next == null) // convention for defunct node
throw new IllegalStateException("Position no longer valid");
return element;
}
public Node<E> getPrev() {
return prev;
}
public Node<E> getNext() {
return next;
}
public void setElement(E e) {
element = e;
}
public void setPrev(Node<E> p) {
prev = p;
}
public void setNext(Node<E> n) {
next = n;
}
}
private Node<E> header; // header sentinel
private Node<E> trailer; // trailer sentinel
private int size = 0; // number of elements in the list
public LinkedPositionalList( ) {
header = new Node<>(null, null, null); // create header
trailer = new Node<>(null, header, null); // trailer is preceded by header
header.setNext(trailer); // header is followed by trailer
}
private Node<E> validate(IPosition<E> p) throws IllegalArgumentException {
if (!(p instanceof Node)) throw new IllegalArgumentException("Invalid p");
Node<E> node = (Node<E>) p; // safe cast
if (node.getNext( ) == null) {// convention for defunct node
throw new IllegalArgumentException("p is no longer in the list");
}
return node;
}
private IPosition<E> position(Node<E> node) {
if (node == header || node == trailer) {
return null; // do not expose user to the sentinels
}
return node;
}
public int size() { return size; }
public boolean isEmpty() { return size == 0; }
public IPosition<E> first() {
return position(header.getNext());
}
public IPosition<E> last() {
return position(trailer.getPrev());
}
public IPosition<E> before(IPosition<E> p) throws IllegalArgumentException {
Node<E> node = validate(p);
return position(node.getPrev());
}
public IPosition<E> after(IPosition<E> p) throws IllegalArgumentException {
Node<E> node = validate(p);
return position(node.getNext());
}
private IPosition<E> addBetween(E e, Node<E> pred, Node<E> succ) {
Node<E> newest = new Node<>(e, pred, succ); // create and link a new node
pred.setNext(newest);
succ.setPrev(newest);
size++;
return newest;
}
public IPosition<E> addFirst(E e) {
return addBetween(e, header, header.getNext( )); // just after the header
}
public IPosition<E> addLast(E e) {
return addBetween(e, trailer.getPrev( ), trailer); // just before the trailer
}
public IPosition<E> addBefore(IPosition<E> p, E e) throws IllegalArgumentException {
Node<E> node = validate(p);
return addBetween(e, node.getPrev( ), node);
}
public IPosition<E> addAfter(IPosition<E> p, E e) throws IllegalArgumentException {
Node<E> node = validate(p);
return addBetween(e, node, node.getNext( ));
}
public E set(IPosition<E> p, E e) throws IllegalArgumentException {
Node<E> node = validate(p);
E answer = node.getElement( );
node.setElement(e);
return answer;
}
public E remove(IPosition<E> p) throws IllegalArgumentException {
Node<E> node = validate(p);
Node<E> predecessor = node.getPrev( );
Node<E> successor = node.getNext( );
predecessor.setNext(successor);
successor.setPrev(predecessor);
size--;
E answer = node.getElement( );
node.setElement(null); // help with garbage collection
node.setNext(null); // and convention for defunct node
node.setPrev(null);
return answer;
}
}
public interface IPosition<E> {
E getElement( ) throws IllegalStateException;
}
public interface IPositionalList <E>{
int size();
boolean isEmpty();
IPosition<E> first();
IPosition<E> last();
IPosition<E> before(IPosition<E> p) throws IllegalArgumentException;
IPosition<E> after(IPosition<E> p) throws IllegalArgumentException;
IPosition<E> addFirst(E e);
IPosition<E> addLast(E e);
IPosition<E> addBefore(IPosition<E> p, E e) throws IllegalArgumentException;
IPosition<E> addAfter(IPosition<E> p, E e) throwsIllegalArgumentException;
E set(IPosition<E> p, E e) throws IllegalArgumentException;
E remove(IPosition<E> p) throws IllegalArgumentException;
}
IPosition
在本例中只是Node
的公共API变体——这是一种比较常见但可疑的做法。
如何创建这种类型的实例?你不。你叫一个能让你得到这种东西的东西然后把它传下去。例如,first()
,它返回一个类型层次结构至少包含IPosition的对象。
例如:
void test() {
IPositionalList<String> list = new LinkedPositionalList<>();
list.addLast("Hello");
list.addLast("World");
IPosition<String> first = list.first();
list.addAfter(first, "there");
}
list将包含[Hello, there, World]。
注意:不鼓励为每个类创建一个接口,尤其是公共类;考虑到LinkedPositionalList是公开的,IPosition<E>
可能是可辩护的,IPositionalList
则不是。
NB2:将你的接口命名为IFoo
,这是一种奇怪的匈牙利符号,是非常古老的,强烈反对的;你的IDE可以告诉你,如果你真的需要知道什么是一个接口或不是;一般来说,这并不重要。它阻碍了重构;如果稍后您改变了主意,将过去用于类的东西变为接口,或者反之亦然,该怎么办?你是否通过添加或删除I
而打破更多?枚举将被命名为ESuit
而不仅仅是Suit
,记录RPerson
而不是人,抽象类应该得到A吗?那么注释接口呢?我们为什么不叫public static strictfp int getFoo()
而叫psfiGetFoo
呢?