class Human { public name: string; private age: number; // 此处修改为使用private修饰符 public constructor(name: string, age: number) { this.name = name; this.age = age; } } const man = new Human('tom', 20); console.log(man.name); // -> tom console.log(man.age); // -> Property 'age' is private and only accessible within class 'Human'.
我们将age属性的修饰符修改为private后,在外部通过man.age对其进行访问,TypeScript在编译阶段就会发现其是一个私有属性并最终将会报错。
注意:在TypeScript编译之后的代码中并没有限制对私有属性的存取操作。
编译后的代码如下:
var Human = /** @class */ (function () { function Human(name, age) { this.name = name; this.age = age; } return Human; }()); var man = new Human('tom', 20); console.log(man.name); // -> tom console.log(man.age); // -> 20
使用private修饰符修饰的属性或者方法在子类中也是不允许访问的,示例如下:
class Human { public name: string; private age: number; public constructor(name: string, age: number) { this.name = name; this.age = age; } } class Woman extends Human { private gender: number = 0; public constructor(name: string, age: number) { super(name, age); console.log(this.age); } } const woman = new Woman('Alice', 18); // -> Property 'age' is private and only accessible within class 'Human'.
在上述示例中由于在父类Human中age属性被设置为private,因此在子类Woman中无法访问到age属性,为了让在子类中允许访问age属性,我们可以使用protected修饰符来对其进行修饰:
class Human { public name: string; protected age: number; // 此处修改为使用protected修饰符 public constructor(name: string, age: number) { this.name = name; this.age = age; } } class Woman extends Human { private gender: number = 0; public constructor(name: string, age: number) { super(name, age); console.log(this.age); } } const woman = new Woman('Alice', 18); // -> 18
当我们将private修饰符用于构造函数时,则表示该类不允许被继承或实例化,示例如下:
class Human { public name: string; public age: number; // 此处修改为使用private修饰符 private constructor(name: string, age: number) { this.name = name; this.age = age; } } class Woman extends Human { private gender: number = 0; public constructor(name: string, age: number) { super(name, age); } } const man = new Human('Alice', 18); // -> Cannot extend a class 'Human'. Class constructor is marked as private. // -> Constructor of class 'Human' is private and only accessible within the class declaration.
当我们将protected修饰符用于构造函数时,则表示该类只允许被继承,示例如下:
class Human { public name: string; public age: number; // 此处修改为使用protected修饰符 protected constructor(name: string, age: number) { this.name = name; this.age = age; } } class Woman extends Human { private gender: number = 0; public constructor(name: string, age: number) { super(name, age); } } const man = new Human('Alice', 18); // -> Constructor of class 'Human' is protected and only accessible within the class declaration.
另外我们还可以直接将修饰符放到构造函数的参数中,示例如下:
class Human { // public name: string; // private age: number; public constructor(public name: string, private age: number) { this.name = name; this.age = age; } } const man = new Human('tom', 20); console.log(man.name); // -> tom console.log(man.age); // -> Property 'age' is private and only accessible within class 'Human'.
3、接口与构造器签名
当我们的项目中拥有很多不同的类时并且这些类之间可能存在某方面的共同点,为了描述这种共同点,我们可以将其提取到一个接口(interface)中用于集中维护,并使用implements关键字来实现这个接口,示例如下:
interface IHuman { name: string; age: number; walk(): void; } class Human implements IHuman { public constructor(public name: string, public age: number) { this.name = name; this.age = age; } walk(): void { console.log('I am walking...'); } }
上述代码在编译阶段能顺利通过,但是我们注意到在Human类中包含constructor构造函数,如果我们想在接口中为该构造函数定义一个签名并让Human类来实现这个接口,看会发生什么:
interface HumanConstructor { new (name: string, age: number); } class Human implements HumanConstructor { public constructor(public name: string, public age: number) { this.name = name; this.age = age; } walk(): void { console.log('I am walking...'); } } // -> Class 'Human' incorrectly implements interface 'HumanConstructor'. // -> Type 'Human' provides no match for the signature 'new (name: string, age: number): any'.