在 Java 中,如何在不访问双端队列 class 中的私有字段的情况下,在双端队列 class 的子 class 中实现新功能?
In Java, how can I implement new functionality in a subclass of a Deque class without access to the private fields in the Deque class?
我正在为我的数据结构课程做作业,我需要知道是否可以在 LinkedOutputRestrictedDeque(LinkedQueue 的子class)中编写一个 enqueueAtFront() 方法,而不更改LinkedQueue 保护而非私有。
所以,这里是问题陈述:
一个输出受限的双端队列支持两端插入,但只支持访问和删除
从前面。您将开发输出受限双端队列的单链接实现。
您将使用名为 OutputRestrictedDequeADT 的新接口扩展提供的 QueueADT 接口
这将声明一个新操作:
void enqueueAtFront(E theElement);
您将开发一个名为 LinkedOutputRestrictedDeque 的新 class。 class 将扩展提供的
LinkedQueue class 并将实现 OutputRestrictedDequeADT 接口。
如果您对 LinkedQueue 进行任何更改 class 那么您必须列出这些更改(以及您的原因
这些更改)在您的执行摘要中。
所以真的,我真正需要做的就是编写 enqueueAtFront() 方法,技术上允许我对 LinkedQueue 进行更改,但我想知道是否可以在不将 LinkedQueue 的字段更改为受保护的情况下实现此目的.如有必要,这里是LinkedQueue的代码:
/*
* TCSS 342
*/
package structures;
import exceptions.EmptyCollectionException;
/**
* A singly-linked implementation of the QueueADT.
*
* @author Alan Fowler - An adaptation of code from several textbooks
* @version 1.1
*
* @param <E>
*/
public class LinkedQueue<E> implements QueueADT<E> {
/**
* The number of elements contained in the queue.
*/
private int mySize;
/**
* A reference to the first node in the queue.
* (The 'head' of the queue.)
*/
private Node<E> myFront;
/**
* A reference to the last node in the queue.
* (The 'tail' of the queue.)
*/
private Node<E> myRear;
/**
* Initialize an empty queue.
*/
public LinkedQueue() {
mySize = 0;
myFront = null;
myRear = null;
}
@Override
public void enqueue(final E theElement) {
if (mySize == 0) { // Make a queue of one element
myFront = new Node<E>(theElement);
myRear = myFront;
} else { // Regular case
myRear.myNext = new Node<E>(theElement);
myRear = myRear.myNext;
}
mySize++;
}
@Override
public E dequeue() {
if (mySize == 0) {
throw new EmptyCollectionException("queue");
}
final E returnValue = myFront.myData;
myFront = myFront.myNext;
mySize--;
return returnValue;
}
@Override
public E first() {
if (mySize == 0) {
throw new EmptyCollectionException("queue");
}
return myFront.myData;
}
@Override
public int size() {
return mySize;
}
@Override
public boolean isEmpty() {
return mySize == 0;
}
/**
* The returned String lists each element in the queue and includes a label for
* the front of the queue.
*
* <p>The format of the returned String is:
* Front -> 8, 6, 7, 5, 3, 0, 9
*/
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
if (mySize > 0) {
sb.append("front -> ");
Node<E> temp = myFront;
for (int i = 0; i < mySize - 1; i++) {
sb.append(temp.myData);
sb.append(", ");
temp = temp.myNext;
}
sb.append(temp.myData);
}
return sb.toString();
}
// Inner Node class
/**
* Represents a node in a singly linked structure.
*
* @author Alan Fowler - An adaptation of code from several textbooks
* @version 1.1
*
* @param <T>
*/
public class Node<T> {
/**
* A reference to the next node in the liked structure.
*/
private Node<T> myNext;
/**
* A reference to the data element held in this node.
*/
private T myData;
/**
* Initialize the node using the specified data element.
*
* @param theData the data element held in this node
*/
Node(final T theData) {
this(theData, null);
}
/**
* Initialize the node using the specified data element and
* the specified next node.
*
* @param theData the data element held in this node
* @param theNext the next node in the linked structure
*/
Node(final T theData, final Node<T> theNext) {
myData = theData;
myNext = theNext;
}
}
}
我是否需要将字段更改为受保护或制作 getters/setters,或者我是否遗漏了一些明显的解决方案?我显然对这些东西很陌生。如果不需要,我只是不想破坏封装。
没有。继承规则在这里是显式;如果您希望子 class 可以访问父字段,则它们必须至少处于 protected
可见性。
也有道理; private
字段表示此信息对父级是显式和独有的,而 protected
字段表示此信息可由父级 class 及其子级使用,是你想要完成的。
如果允许您对 LinkedQueue
进行更改,您最好为其添加一些方法。例如,您可以将受保护的方法enqueueAtFront
添加到LinkedQueue
,并在新的class中使其成为public。它对封装的损害较小。
保护字段会使它们暴露给您 class 的任何子class。一些错误的代码可能会破坏 class 合同。例如,有人可能忘记更新字段 mySize
。当您添加受保护的方法时,您可以确保字段安全,只允许有限的操作集。
我正在为我的数据结构课程做作业,我需要知道是否可以在 LinkedOutputRestrictedDeque(LinkedQueue 的子class)中编写一个 enqueueAtFront() 方法,而不更改LinkedQueue 保护而非私有。
所以,这里是问题陈述:
一个输出受限的双端队列支持两端插入,但只支持访问和删除 从前面。您将开发输出受限双端队列的单链接实现。
您将使用名为 OutputRestrictedDequeADT 的新接口扩展提供的 QueueADT 接口 这将声明一个新操作:
void enqueueAtFront(E theElement);
您将开发一个名为 LinkedOutputRestrictedDeque 的新 class。 class 将扩展提供的 LinkedQueue class 并将实现 OutputRestrictedDequeADT 接口。
如果您对 LinkedQueue 进行任何更改 class 那么您必须列出这些更改(以及您的原因 这些更改)在您的执行摘要中。
所以真的,我真正需要做的就是编写 enqueueAtFront() 方法,技术上允许我对 LinkedQueue 进行更改,但我想知道是否可以在不将 LinkedQueue 的字段更改为受保护的情况下实现此目的.如有必要,这里是LinkedQueue的代码:
/*
* TCSS 342
*/
package structures;
import exceptions.EmptyCollectionException;
/**
* A singly-linked implementation of the QueueADT.
*
* @author Alan Fowler - An adaptation of code from several textbooks
* @version 1.1
*
* @param <E>
*/
public class LinkedQueue<E> implements QueueADT<E> {
/**
* The number of elements contained in the queue.
*/
private int mySize;
/**
* A reference to the first node in the queue.
* (The 'head' of the queue.)
*/
private Node<E> myFront;
/**
* A reference to the last node in the queue.
* (The 'tail' of the queue.)
*/
private Node<E> myRear;
/**
* Initialize an empty queue.
*/
public LinkedQueue() {
mySize = 0;
myFront = null;
myRear = null;
}
@Override
public void enqueue(final E theElement) {
if (mySize == 0) { // Make a queue of one element
myFront = new Node<E>(theElement);
myRear = myFront;
} else { // Regular case
myRear.myNext = new Node<E>(theElement);
myRear = myRear.myNext;
}
mySize++;
}
@Override
public E dequeue() {
if (mySize == 0) {
throw new EmptyCollectionException("queue");
}
final E returnValue = myFront.myData;
myFront = myFront.myNext;
mySize--;
return returnValue;
}
@Override
public E first() {
if (mySize == 0) {
throw new EmptyCollectionException("queue");
}
return myFront.myData;
}
@Override
public int size() {
return mySize;
}
@Override
public boolean isEmpty() {
return mySize == 0;
}
/**
* The returned String lists each element in the queue and includes a label for
* the front of the queue.
*
* <p>The format of the returned String is:
* Front -> 8, 6, 7, 5, 3, 0, 9
*/
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
if (mySize > 0) {
sb.append("front -> ");
Node<E> temp = myFront;
for (int i = 0; i < mySize - 1; i++) {
sb.append(temp.myData);
sb.append(", ");
temp = temp.myNext;
}
sb.append(temp.myData);
}
return sb.toString();
}
// Inner Node class
/**
* Represents a node in a singly linked structure.
*
* @author Alan Fowler - An adaptation of code from several textbooks
* @version 1.1
*
* @param <T>
*/
public class Node<T> {
/**
* A reference to the next node in the liked structure.
*/
private Node<T> myNext;
/**
* A reference to the data element held in this node.
*/
private T myData;
/**
* Initialize the node using the specified data element.
*
* @param theData the data element held in this node
*/
Node(final T theData) {
this(theData, null);
}
/**
* Initialize the node using the specified data element and
* the specified next node.
*
* @param theData the data element held in this node
* @param theNext the next node in the linked structure
*/
Node(final T theData, final Node<T> theNext) {
myData = theData;
myNext = theNext;
}
}
}
我是否需要将字段更改为受保护或制作 getters/setters,或者我是否遗漏了一些明显的解决方案?我显然对这些东西很陌生。如果不需要,我只是不想破坏封装。
没有。继承规则在这里是显式;如果您希望子 class 可以访问父字段,则它们必须至少处于 protected
可见性。
也有道理; private
字段表示此信息对父级是显式和独有的,而 protected
字段表示此信息可由父级 class 及其子级使用,是你想要完成的。
如果允许您对 LinkedQueue
进行更改,您最好为其添加一些方法。例如,您可以将受保护的方法enqueueAtFront
添加到LinkedQueue
,并在新的class中使其成为public。它对封装的损害较小。
保护字段会使它们暴露给您 class 的任何子class。一些错误的代码可能会破坏 class 合同。例如,有人可能忘记更新字段 mySize
。当您添加受保护的方法时,您可以确保字段安全,只允许有限的操作集。