Доступ к закрытому члену класса только внутри класса, который имеет экземпляр этого класса - PullRequest
0 голосов
/ 28 апреля 2020

Я реализую связанный список. У меня есть два класса Node и SingleLinkedList. Теперь мне нужно получить доступ к закрытому члену класса Node из класса SingleLinkedList, но снаружи я бы этого не сделал; таким образом я могу вернуть Node экземпляр из SingleLinkedList, и пользователи не могут присоединиться ко всей структуре данных с этим узлом. В Java, когда у класса есть объект другого класса (композиции), это можно сделать, в C ++ есть дружественные классы. Как я могу сделать это в Javascript?

Ниже приведена «примерная игрушка», которую я реализую, чтобы проверить мои знания, полученные до сих пор, и посмотреть, какие проблемы возникают

  class Node {
             next = null;
             constructor(value) {
                this.value = value;

             }
          }

          class SingleLinkedList {
             #size = 0;
             #head = null;
             #tail = null;

             // read only get accessor property
             get size() {
                return this.#size;
             }

             isEmpty() {
                return this.#size === 0;
             }

            // insert a new Node (in tail) with the desired value
         push(value) {
            const node = new Node(value);

            if (this.isEmpty()) {
               this.#head = node;
            } else {
               this.#tail.next = node;
            }

            // the following instructions are common to both the cases.
            this.#tail = node;
            this.#size++;

            // to allow multiple push call
            return this;
         }



        get(index){
        if(index<0 || index>=this.#size)
           return null;

        let current = this.#head;


        return current.value;
     }


          }

          const myLinkedList = new SingleLinkedList();
          myLinkedList.push(3).push(5);

Например, если я закрываю свойство next класса Node
, я больше не могу получить доступ к переменной внутри моего SingleLinkedClass. Вместо этого, если я оставлю подобный код и верну экземпляр Node из какой-либо функции, пользователь может присоединиться почти ко всей моей структуре, используя следующее свойство. Существует ли какое-нибудь, возможно, простое решение в Javascript? Я хочу быть максимально ясным. Итак, вот что я хочу сделать:

  class Node {
         next = null;
         constructor(value) {
            this.value = value;

         }
      }

      class SingleLinkedList {
         #size = 0;
         #head = null;
         #tail = null;

         // read only get accessor property
         get size() {
            return this.#size;
         }

         isEmpty() {
            return this.#size === 0;
         }


        // insert a new Node (in tail) with the desired value
     push(value) {
        const node = new Node(value);

        if (this.isEmpty()) {
           this.#head = node;
        } else {
           this.#tail.next = node;
        }

        // the following instructions are common to both the cases.
        this.#tail = node;
        this.#size++;

        // to allow multiple push call
        return this;
     }


        get(index){
        if(index<0 || index>=this.#size)
           return null;

        let current = this.#head;


        return current; //NOW RETURN A NODE
     }

      const myLinkedList = new SingleLinkedList();
      myLinkedList.push(3).push(5);

      const myNode = myLinkedList.get(0); //RETURN NODE

Теперь в приведенном выше коде get() возвращает узел, и с его помощью вы можете сканировать весь список. Не хорошо. Таким образом, я хочу сделать:

class Node {
         #next = null; //PRIVATE MEMBER
         constructor(value) {
            this.value = value;

         }
      }

      class SingleLinkedList {
         #size = 0;
         #head = null;
         #tail = null;

         // read only get accessor property
         get size() {
            return this.#size;
         }

         isEmpty() {
            return this.#size === 0;
         }


        // insert a new Node (in tail) with the desired value
     push(value) {
        const node = new Node(value);

        if (this.isEmpty()) {
           this.#head = node;
        } else {
           this.#tail.#next = node; //ERROR
        }

        // the following instructions are common to both the cases.
        this.#tail = node;
        this.#size++;

        // to allow multiple push call
        return this;
     }



        get(index){
        if(index<0 || index>=this.#size)
           return null;

        let current = this.#head;


        return current; //NOW RETURN A NODE
     }



      }

      const myLinkedList = new SingleLinkedList();
      myLinkedList.push(3).push(5);
      console.log(myLinkedList.toString());
      const myNode = myLinkedList.get(0); //RETURN NODE,NO MORE A PROBLEM

С этой последней версией, когда я возвращаю Node из get(), больше не проблема, потому что член класса Node, а именно #next, является частным, но в таким образом у меня возникает ошибка, потому что даже внутри SingleLinkedClass член #next не виден.

Надеюсь, это прояснит мой вопрос

1 Ответ

2 голосов
/ 28 апреля 2020

Частный идентификатор ограничен лексической областью, поэтому #size и такие недоступны за пределами SingleLinkedList. Но есть несколько способов сделать это.

Самое простое - сделать Node в пределах SingleLinkedList:

"use strict";
class SingleLinkedList {
    #size = 0;
    
    constructor(size) {
        this.#size = size;
    }

    static Node = class Node {
        example(list) {
            console.log(`The size of the list is ${list.#size}`);
        }
    }
}
const Node = SingleLinkedList.Node;

// The `Node` code has access to `SingleLinkedList`'s private field:
const l = new SingleLinkedList(42);
const n = new Node();
n.example(l); // "The size of the list is ${getSize(list)}"

Поскольку область действия является лексической, и весь код Node находится в области действия SingleLinkedList, это прекрасно работает.

Если вы не хотите, чтобы они были вложенными, вы можете заставить SingleLinkedList предоставить Node функцию, к которой только Node имеет доступ, что позволит Node получать информацию из личных полей SingleLinkedlist. Вот пример, смотрите комментарии:

"use strict";
const {Node, SingleLinkedList} = (() => {
    // A function SingleLinkedList will fill in
    let getSize;

    // Create the class
    class SingleLinkedList {
        #size = 0;
        
        constructor(size) {
            this.#size = size;
        }

        // This is a temporary function for filling in `getSize`
        static boot() {
            getSize = list => list.#size;
        }
    }

    // Fill in `getSize`
    SingleLinkedList.boot();
    delete SingleLinkedList.boot;

    // Find the `Node` class, which uses `getSize`
    class Node {
        example(list) {
            console.log(`The size of the list is ${getSize(list)}`);
        }
    }

    // Return them; `getSize` is entirely private to the code
    // in this function, nothing else can use it
    return {Node, SingleLinkedList}
})();

// The `Node` code has access to `SingleLinkedList`'s private field:
const l = new SingleLinkedList(42);
const n = new Node();
n.example(l); // "The size of the list is ${getSize(list)}"

Это работает, потому что фактическое использование #size находится в пределах области его существования.

Другой вариант - сделать Node в пределах SingleLinkedList:

...