在 TypeScript 中访问外部 class 的成员
Access members of outer class in TypeScript
从 TypeScript 1.6 开始,我们可以使用 . In other OOP-centric languages like Java, inner classes can access members of the outer class, even private ones.
轻松创建内部 类
此行为类似于闭包的概念,其中函数可以从定义它的范围访问变量。
为什么我不能在 TypeScript 中实现这个? ECMAScript 2015 中的 类 规范在这里起作用吗?
呈现预期行为的代码:
class OuterClass {
private outerField = 1337;
public InnerClass = class {
public accessOuter() {
return this.outerField; // outerField not defined
}
}
}
var outer = new OuterClass();
var inner = new outer.InnerClass();
var win = inner.accessOuter();
如果查看代码的编译 java 脚本,就更容易理解为什么不能这样做:
var OuterClass = (function () {
function OuterClass() {
this.outerField = 1337;
this.InnerClass = (function () {
function class_1() {
}
class_1.prototype.accessOuter = function () {
return this.outerField; // outerField not defined
};
return class_1;
}());
}
return OuterClass;
}());
如您所见,outerField
被定义为 OuterClass
的成员,如下所示:
this.outerField = 1337;
当您尝试在 InnerClass
中访问它时,您会:
return this.outerField;
但是这里的this
是class_1
的实例而不是OuterClass
所以this
中没有outerField
。
此外,您无法从内部 class 访问外部 class.
的实例
java中的解决方法是这样的:
class OuterClass {
private int outerField = 1337;
public class InnerClass {
public int accessOuter() {
return OuterClass.this.outerField;
}
}
}
但是 typescript/javascript 中没有 OuterClass.this.outerField
的等价物。
查看打字稿内部 classes 更像是 java 中的静态内部 classes,但在这里你也只能访问 public 属性:
class OuterClass {
public static outerField = 1337; // has to be public
public InnerClass = class {
public accessOuter() {
return OuterClass.outerField;
}
}
}
您可以将外部 class 的实例传递给内部 class:
class OuterClass {
public outerField = 1337;
public InnerClass = class {
constructor(private parent: OuterClass) {}
public accessOuter() {
return this.parent.outerField;
}
}
}
但同样,您需要 outerField
public.
编辑
如果你想实现一些模拟所需行为的东西(也就是说,内部 class 实例将可以访问私有外部 class 成员),那么你可以做一些事情像这样:
interface OuterClassProxy {
outerField: number;
}
interface IInnerClass {}
class OuterClass {
private outerField = 1337;
static InnerClass = class implements IInnerClass {
constructor(private parent: OuterClassProxy) {}
public accessOuter() {
return this.parent.outerField;
}
}
public createInnerClass(): IInnerClass {
let outerClassInstance = this;
return new OuterClass.InnerClass({
get outerField(): number {
return outerClassInstance.outerField;
},
set outerField(value: number) {
outerClassInstance.outerField = value;
}
});
}
}
这是一项相当多的工作,但它会完成的。
@Nitzan 的回答很棒。我只是想补充一点,我最近想到了这个,也许它有帮助:
class Outer {
constructor() {
this.val = 1337;
}
get Inner() {
let Outer = this;
return class {
accessVal() { return Outer.val; }
}
}
}
new (new Outer()).Inner().accessVal(); // 1337
以下是在 Typescript 中执行此操作的正确方法:
class OuterClass {
private outerField = 1337;
get InnerClass() {
const thatOuterField = this.outerField // <-- Notice this addition
return class {
public accessOuter() {
return thatOuterField; // outerField not defined
}
}
}
}
let outer = new OuterClass();
let inner = new outer.InnerClass();
let win = inner.accessOuter();
alert(win); // test works!
不需要任何复杂的东西。
这个对我来说效果不是很好:
function use<T>(value: T) {return new class {with<U>(f: (value: T) => U) {return f(value)}}}
class OuterClass {
private outerField = 1337;
InnerClass = use(this).with(outerThis => class {
accessOuter() {
return outerThis.outerField; // outerField not defined
}
}
}
const outer = new OuterClass()
const inner = new outer.InnerClass()
const win = inner.accessOuter()
console.log(win)
从 TypeScript 1.6 开始,我们可以使用
此行为类似于闭包的概念,其中函数可以从定义它的范围访问变量。
为什么我不能在 TypeScript 中实现这个? ECMAScript 2015 中的 类 规范在这里起作用吗?
呈现预期行为的代码:
class OuterClass {
private outerField = 1337;
public InnerClass = class {
public accessOuter() {
return this.outerField; // outerField not defined
}
}
}
var outer = new OuterClass();
var inner = new outer.InnerClass();
var win = inner.accessOuter();
如果查看代码的编译 java 脚本,就更容易理解为什么不能这样做:
var OuterClass = (function () {
function OuterClass() {
this.outerField = 1337;
this.InnerClass = (function () {
function class_1() {
}
class_1.prototype.accessOuter = function () {
return this.outerField; // outerField not defined
};
return class_1;
}());
}
return OuterClass;
}());
如您所见,outerField
被定义为 OuterClass
的成员,如下所示:
this.outerField = 1337;
当您尝试在 InnerClass
中访问它时,您会:
return this.outerField;
但是这里的this
是class_1
的实例而不是OuterClass
所以this
中没有outerField
。
此外,您无法从内部 class 访问外部 class.
java中的解决方法是这样的:
class OuterClass {
private int outerField = 1337;
public class InnerClass {
public int accessOuter() {
return OuterClass.this.outerField;
}
}
}
但是 typescript/javascript 中没有 OuterClass.this.outerField
的等价物。
查看打字稿内部 classes 更像是 java 中的静态内部 classes,但在这里你也只能访问 public 属性:
class OuterClass {
public static outerField = 1337; // has to be public
public InnerClass = class {
public accessOuter() {
return OuterClass.outerField;
}
}
}
您可以将外部 class 的实例传递给内部 class:
class OuterClass {
public outerField = 1337;
public InnerClass = class {
constructor(private parent: OuterClass) {}
public accessOuter() {
return this.parent.outerField;
}
}
}
但同样,您需要 outerField
public.
编辑
如果你想实现一些模拟所需行为的东西(也就是说,内部 class 实例将可以访问私有外部 class 成员),那么你可以做一些事情像这样:
interface OuterClassProxy {
outerField: number;
}
interface IInnerClass {}
class OuterClass {
private outerField = 1337;
static InnerClass = class implements IInnerClass {
constructor(private parent: OuterClassProxy) {}
public accessOuter() {
return this.parent.outerField;
}
}
public createInnerClass(): IInnerClass {
let outerClassInstance = this;
return new OuterClass.InnerClass({
get outerField(): number {
return outerClassInstance.outerField;
},
set outerField(value: number) {
outerClassInstance.outerField = value;
}
});
}
}
这是一项相当多的工作,但它会完成的。
@Nitzan 的回答很棒。我只是想补充一点,我最近想到了这个,也许它有帮助:
class Outer {
constructor() {
this.val = 1337;
}
get Inner() {
let Outer = this;
return class {
accessVal() { return Outer.val; }
}
}
}
new (new Outer()).Inner().accessVal(); // 1337
以下是在 Typescript 中执行此操作的正确方法:
class OuterClass {
private outerField = 1337;
get InnerClass() {
const thatOuterField = this.outerField // <-- Notice this addition
return class {
public accessOuter() {
return thatOuterField; // outerField not defined
}
}
}
}
let outer = new OuterClass();
let inner = new outer.InnerClass();
let win = inner.accessOuter();
alert(win); // test works!
不需要任何复杂的东西。
这个对我来说效果不是很好:
function use<T>(value: T) {return new class {with<U>(f: (value: T) => U) {return f(value)}}}
class OuterClass {
private outerField = 1337;
InnerClass = use(this).with(outerThis => class {
accessOuter() {
return outerThis.outerField; // outerField not defined
}
}
}
const outer = new OuterClass()
const inner = new outer.InnerClass()
const win = inner.accessOuter()
console.log(win)