【问题标题】: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?在 Java 中,如何在不访问 Deque 类中的私有字段的情况下在 Deque 类的子类中实现新功能?
【发布时间】:2019-01-31 20:42:58
【问题描述】:

我正在为我的数据结构课程做作业,我需要知道是否可以在 LinkedOutputRestrictedDeque(LinkedQueue 的子类)中编写 enqueueAtFront() 方法,而无需将 LinkedQueue 的字段更改为受保护而不是私有。

所以,这里是问题陈述:

输出受限的双端队列支持从两端插入,但只支持访问和删除 从前面。您将开发一个输出受限双端队列的单链接实现。

您将使用名为 OutputRestrictedDequeADT 的新接口扩展提供的 QueueADT 接口 这将声明一个新操作:

void enqueueAtFront(E theElement);

您将开发一个名为 LinkedOutputRestrictedDeque 的新类。此类将扩展提供的 LinkedQueue 类,并将实现 OutputRestrictedDequeADT 接口。

如果您对 LinkedQueue 类进行了任何更改,那么您必须列出这些更改(以及您更改的原因) 这些变化)在您的执行摘要中。

所以说真的,我真正需要做的就是编写 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;
        }
    }


}

我是否需要将字段更改为受保护或创建 getter/setter,或者我是否缺少一些明显的解决方案?我显然对这些东西很陌生。如果不需要的话,我只是不想破坏封装。

【问题讨论】:

    标签: java inheritance queue encapsulation deque


    【解决方案1】:

    如果允许您对LinkedQueue 进行更改,您最好为其添加一些方法。例如,您可以将受保护的方法enqueueAtFront 添加到LinkedQueue,并在新类中将其公开。它对封装的损害会更小。

    使字段受保护会将它们公开给您类的任何子类。一些错误的代码可能会破坏类契约。例如,有人可能忘记更新字段mySize。当您添加受保护的方法时,您可以确保您的字段安全,只允许有限的一组操作。

    【讨论】:

      【解决方案2】:

      没有。继承规则在这里是显式的;如果您希望子类能够访问父类的字段,它们必须至少在 protected 可见性中。

      这也是有道理的; private 字段表示此信息是显式的并且是父类独有的,而protected 字段表示此信息可由父类及其子类使用,想要完成。

      【讨论】:

      • 啊,我是这么想的。感谢您的回复。
      猜你喜欢
      • 1970-01-01
      • 2010-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-19
      • 2018-08-29
      • 2010-10-30
      • 2015-06-02
      相关资源
      最近更新 更多