从内置类型Array, Error, Map等类型继承稍微有点特殊,不过对于target是ES6/ES2015之上的版本,你可以不用考虑。
简单来说,对于这些类,你可能需要使用setPrototypeOf,或者__proto__来维护原型链。
class MsgError extends Error {
constructor(m: string) {
super(m);
Object.setPrototypeOf(this, MsgError.prototype);
}
sayHello() {
return "hello " + this.message;
}
}
const err: MsgError = new MsgError('abc');
console.log(err.sayHello());
不过现在一般目标代码ES6/ES2015都没有什么问题,所以这个问题基本可以忽略。
TypeScript可以使用public/protected/private来控制成员变量或者方法的对外可见性。
对外可见,也是默认的行为。这些方法或变量可以通过实例变量任意的访问。
class Greeter {
public greet() {
console.log("Hi!");
}
}
const g: Greeter = new Greeter();
g.greet()
因为public是默认行为,所以这里的public是可以不加的。
只有自己和子类可以访问。
class Greeter {
protected greet() {
console.log("Hi!");
}
}
class NewGreeter extends Greeter {
public newGreet() {
this.greet();
console.log("Hi in NewGreeter");
}
}
const g: NewGreeter = new NewGreeter();
// g.greet() // Error
g.newGreet();
子类可以通过newGreet()调用父类的greet()方法,但是不能直接调用g.greet()。
子类可以通过重新定义,来暴露父类的protected成员。但是类型要保持兼容。
class Greeter {
protected m = 10;
protected greet() {
console.log("Hi!");
}
}
class NewGreeter extends Greeter {
public m = 15;
public newGreet() {
this.greet();
console.log("Hi in NewGreeter");
}
}
const g: NewGreeter = new NewGreeter();
console.log(g.m);
通常来说,这样的暴露protected成员是没有意义的。
由于public是默认行为,可以不加。所以这里更多的是要提醒,重新设置成员变量初值的时候要小心检查是否要加上protected,否则很容易就把原来的protected变量给暴露出来了。
是否能够通过基类的引用来访问protected变量,在不同的语言里面有不同的行为。
在Java里面是合法的,但是在C#和C++里面是非法的。TypeScript参照的是C#和C++里面的方式,所以这样是非法的。
class Base {
protected x: number = 1;
}
class Derived1 extends Base {
protected x: number = 2;
}
class Derived2 extends Base {
f1(other: Derived2) {
other.x = 10;
}
f2(other: Base) {
// other.x = 20; <-- Error
}
}
Private很简单,就是除了自己,就算是子类也不能访问。
class Base {
private x = 1;
}
class Derived extends Base {
showX() {
// console.log(this.x); <-- Error, x cannot be accessed.
}
}
Derived类也是不能访问x变量的。
由于private成员对于子类也是不可见的,所以子类也不能重新定义可见性。
class Base {
private x = 1;
}
class Derived extends Base {
protected x = 5;
}
编译阶段就报错了。
TypeScript是允许跨实例访问private成员的。
class A {
private x: number = 5;
public sameAs(other: A) {
return this.x === other.x;
}
}
TypeScript的private,只用在编译期,运行期,private的标签就被完全移除了。所以一旦到了JavaScript的领域,就没有了这里的private。
因此,你可以通过中括号来访问private成员。
class A {
private x: number = 5;
public sameAs(other: A) {
return this.x === other.x;
}
}
const a: A = new A();
console.log(a['x']);
这样是可以访问的。
JavaScript有定义使用”#”开头的成员是私有的,这个用法和TypeScript的private尽管含义差不多,但是不是一个东西。TypeScript的private在编译成JavaScript的时候,会被全部抹除。如果希望在JavaScript里面仍然有效,应该使用JavaScript的”#”成员。
留言与评论(共有 0 条评论) “” |