简体   繁体   English

在Java中,如何在Deque类的子类中实现新功能而不访问Deque类中的私有字段?

[英]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?

I'm doing an assignment for my data structures course, and I need to know if it's possible to write an enqueueAtFront() method in LinkedOutputRestrictedDeque, a subclass of LinkedQueue, without changing the fields of LinkedQueue to protected rather than private. 我正在为数据结构课程做作业,我想知道是否有可能在LinkedQueue的子类LinkedOutputRestrictedDeque中编写enqueueAtFront()方法,而无需将LinkedQueue的字段更改为protected而不是private。

So, here is the problem statement: 因此,这是问题陈述:

An output-restricted double-ended queue supports insertions from both ends, but accesses and deletions only from the front. 有输出限制的双端队列支持两端插入,但只能从前端进行访问和删除。 You will develop a singly linked implementation of an output-restricted double-ended queue. 您将开发输出受限的双端队列的单链接实现。

You will extend the provided QueueADT interface with a new interface called OutputRestrictedDequeADT which will declare one new operation: 您将使用名为OutputRestrictedDequeADT的新接口扩展提供的QueueADT接口,该接口将声明一个新操作:

void enqueueAtFront(E theElement); void enqueueAtFront(E theElement);

You will develop a new class called LinkedOutputRestrictedDeque. 您将开发一个名为LinkedOutputRestrictedDeque的新类。 This class will extend the provided LinkedQueue class and will implement the OutputRestrictedDequeADT interface. 此类将扩展提供的LinkedQueue类,并将实现OutputRestrictedDequeADT接口。

If you make ANY changes to the LinkedQueue class then you MUST list these changes (and your reasons for these changes) in your executive summary. 如果对LinkedQueue类进行了任何更改,则必须在执行摘要中列出这些更改(以及这些更改的原因)。

So really, all I really need to do is write the enqueueAtFront() method, and I am technically allowed to make changes to LinkedQueue, but I want to know if it's possible to achieve this without changing LinkedQueue's fields to protected. 因此,实际上,我真正需要做的就是编写enqueueAtFront()方法,并且从技术上讲我可以对LinkedQueue进行更改,但是我想知道是否有可能在不将LinkedQueue的字段更改为protected的情况下实现这一点。 Here is the code of LinkedQueue if necessary: 如果需要,这是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;
        }
    }


}

Do I need to change the fields to protected or make getters/setters, or am I missing some obvious solution? 我是否需要将字段更改为“保护”或“获取/设置”,还是缺少一些明显的解决方案? I'm obviously fairly new to this stuff. 我显然对这个东西还很陌生。 I just don't want to ruin the encapsulation if I don't have to. 我只是不想破坏封装,而不必这样做。

If you are allowed to make changes to LinkedQueue , you better add some method to it. 如果允许您对LinkedQueue进行更改,则最好向其中添加一些方法。 For example, you can add protected method enqueueAtFront to LinkedQueue , and make it public in new class. 例如,您可以将受保护的方法enqueueAtFront添加到LinkedQueue ,并将其在新类中公开。 It will do less damage to encapsulation. 它将减少对封装的损坏。

Making fields protected will expose them to any subclass of your class. 使字段受保护会将它们暴露给您类的任何子类。 Some wrong code may break class contract. 一些错误的代码可能会破坏班级合同。 For example, someone may forget to update field mySize . 例如,某人可能会忘记更新字段mySize When you add protected methods you keep you fields safe, allowing only limited set of operations. 添加受保护的方法时,可以确保字段安全,仅允许有限的一组操作。

No. Inheritance rules are explicit here; 不会。继承规则在这里是明确的 if you want a subclass to have access to the parent's fields, they must be at least in protected visibility. 如果您希望子类能够访问父级的字段,则它们必须至少处于protected可见性中。

It also makes sense; 这也是有道理的; a private field would indicate that this information is explicit and exclusive to the parent, whereas a protected field indicates that this information can be used by the parent class and its children, which is what you want to accomplish. private字段将指示该信息对父项是显式的并且是父项专有的,而protected字段指示该信息可被父类及其子级使用,这您想要完成的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM