【问题标题】:B extends A: set in B will overwrite getB 扩展 A:在 B 中设置将覆盖 get
【发布时间】:2015-12-11 18:25:55
【问题描述】:

TypeScript:view on playground

class A {
    protected _name: string = ""

    set name(name: string) {
        this._name = name
    }   
    get name() {
        return this._name
    }
}

class B extends A {
    protected _name: string = ""

    set name(name: string) {
        this._name = name + "B"
    }
}

在编译的 B 类中,这将覆盖 set AND get 的定义:

Object.defineProperty(B.prototype, "name", {
    set: function (name) {
        this._name = name + "B";
    },
    enumerable: true,
    configurable: true
});

结果是,get name 不再适用于 B 类:

let b = new B()
b.name = "test"
console.log(b.name) // undefined

有没有办法从A类继承getter?

【问题讨论】:

标签: javascript typescript ecmascript-6 getter-setter


【解决方案1】:

以下代码在 TypeScript 编译器中运行,没有任何错误:

class A {
   protected _name: string = ""

   set name(name: string) {
       this._name = name
   }   
   get name() {
       return this._name
   }
}

class B extends A {
   // Removed _name declaration here

   set name(name: string) {
       super["name"] = name + "B"      // <=== Using super here
   }
   get name() {
       return super["name"]            // <=== And here
   }
}

var b = new B();
b.name = "foo";
console.log(b.name); // "fooB"

与@Crowder 的代码的唯一区别是,我使用的是super["name"] 而不是super.name。如果您使用super.name,编译器将发出此错误:Only public and protected methods of the base class are accessible via the 'super' keyword。请注意:TypeScript 在发现错误时仍会编译,因此使用super.name 也可以,尽管有错误。

【讨论】:

  • 听起来您在A 中的name 属性被意外宣布为私有。没有理由对静态属性名称使用括号表示法,而是应该修复编译器错误(警告)的原因。
  • @Bergi:name 不是私人的。编译器抱怨,因为只有基类的公共和受保护的方法可以通过“超级”关键字访问,而name 不是方法。当然,括号符号只是一种技巧,可以绕过编译器警告,因为super.name 也可以。
  • 您是否尝试将此作为错误报告给打字稿?所有属性,不仅是方法,都应该可以通过super获得。
  • 我不知道它在哪里或是否在说什么,以及究竟是什么。但它显然应该在编译器中进行更改,必要时可能在规范中进行更改。不应要求此 hack 来抑制此错误。
  • 谢谢@MarcG,这应该是公认的答案:)