我正在实现一个Linked List.我有两个类,分别是 Node
和 SingleLinkedList
. 现在,我需要访问一个私人成员的。Node
阶层 SingleLinkedList
类,但在外面,我想这是不可能的;这样,我可以返回一个 Node
例子 SingleLinkedList
而用户不能用该Node加入所有的数据结构。在Java中当一个类有了另一个类的对象(composition)就可以做到这一点,在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
是不可见的。
我希望这能澄清我的问题
私有标识符的范围是词法的,所以 #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
: