在 TypeScript 中访问外部类的成员

Posted

技术标签:

【中文标题】在 TypeScript 中访问外部类的成员【英文标题】:Access members of outer class in TypeScript 【发布时间】:2016-12-08 09:55:37 【问题描述】:

从 TypeScript 1.6 开始,我们可以使用 class expressions 轻松创建内部类。在其他以 OOP 为中心的语言(如 Java)中,内部类可以访问外部类的成员 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();

【问题讨论】:

请参阅***.com/a/45244695/279393 了解实现此目的的另一种方法。 【参考方案1】:

如果您查看代码的已编译 javascript,就会更容易理解为什么不能这样做:

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;

但这里的thisclass_1 的实例,而不是OuterClass,所以this 中没有outerField。 此外,您无法从内部类访问外部类的实例。

这个在java中的解决方式是这样的:

class OuterClass 
    private int outerField = 1337;

    public class InnerClass 
        public int accessOuter() 
            return OuterClass.this.outerField;
        
    

但 typescript/javascript 中没有与 OuterClass.this.outerField 等效的内容。 看看 typescript 内部类更像 java 中的静态内部类,但在这里你也只能访问公共属性:

class OuterClass 
    public static outerField = 1337; // has to be public

    public InnerClass = class  
        public accessOuter() 
            return OuterClass.outerField;
        
    

您可以将外部类的实例传递给内部类:

class OuterClass 
    public outerField = 1337;

    public InnerClass = class 
        constructor(private parent: OuterClass) 

        public accessOuter() 
            return this.parent.outerField;
        
    

但同样,您需要公开outerField


编辑

如果你想实现一些模拟所需行为的东西(也就是说,内部类实例可以访问私有的外部类成员),那么你可以这样做:

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;
            
        );
    

这是相当多的工作,但它会做到的。

【讨论】:

【参考方案2】:

@Nitzan 的回答很棒。我只是想补充一下,我最近想出了这个,也许它有帮助:

class Outer 

    constructor() 
        this.val = 1337;
    

    get Inner() 
        let Outer = this;
        return class 
            accessVal()  return Outer.val; 
        
    



new (new Outer()).Inner().accessVal(); // 1337

【讨论】:

为使用它的内部类添加一个接口可能是个好主意【参考方案3】:

这是在 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!

不需要任何复杂的东西。

【讨论】:

这是 Kosmas 6 个月前发布的相同方法 虽然你不能修改 outerField...【参考方案4】:

这个对我来说并没有那么糟糕:

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 中访问外部类的成员的主要内容,如果未能解决你的问题,请参考以下文章

外部类与内部类的访问

如何从 Kotlin 的内部类访问外部类的成员?

局部内部类和成员内部类

5.7 内部类

内部类的使用类型

内部类和外部类的实例变量可以共存