仅在具有 class 实例的 class 中访问 class 的私有成员
Access to private member of a class only inside a class that has an instance of that class
我正在实现一个链表。
我有两个 classes Node
和 SingleLinkedList
。现在我需要从 SingleLinkedList
class 访问 Node
class 的私有成员,但在外部我认为这是不可能的;通过这种方式,我可以 return 来自 SingleLinkedList
的 Node
实例,并且用户无法使用该节点访问所有数据结构。在 Java 中,当一个 class 具有另一个 class 的对象(组合)时可以这样做,在 C++ 中有朋友 classes。我如何在 Java 脚本中执行此操作?
以下是我正在实施的 "example toy" 以测试我目前所掌握的知识并查看会出现什么问题
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);
例如,如果我将 class Node
的 next
属性 设为私有
我无法再访问 SingleLinkedClass
中的变量。相反,如果我保留这样的代码,并且我 return 来自某个函数的 Node
实例,用户可以使用下一个 属性 访问我几乎所有的结构。 Java脚本中是否存在一些可能简单的解决方案?
我想尽可能清楚。因此我想做的是:
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()
return 一个节点,你可以用它扫描整个列表。不好。因此我想做:
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
使用最后一个版本,当我 return 来自 get()
的节点不再是问题,因为 class 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
:
内
我正在实现一个链表。
我有两个 classes Node
和 SingleLinkedList
。现在我需要从 SingleLinkedList
class 访问 Node
class 的私有成员,但在外部我认为这是不可能的;通过这种方式,我可以 return 来自 SingleLinkedList
的 Node
实例,并且用户无法使用该节点访问所有数据结构。在 Java 中,当一个 class 具有另一个 class 的对象(组合)时可以这样做,在 C++ 中有朋友 classes。我如何在 Java 脚本中执行此操作?
以下是我正在实施的 "example toy" 以测试我目前所掌握的知识并查看会出现什么问题
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);
例如,如果我将 class Node
的 next
属性 设为私有
我无法再访问 SingleLinkedClass
中的变量。相反,如果我保留这样的代码,并且我 return 来自某个函数的 Node
实例,用户可以使用下一个 属性 访问我几乎所有的结构。 Java脚本中是否存在一些可能简单的解决方案?
我想尽可能清楚。因此我想做的是:
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()
return 一个节点,你可以用它扫描整个列表。不好。因此我想做:
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
使用最后一个版本,当我 return 来自 get()
的节点不再是问题,因为 class 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
: