TypeScript入门教程(四) - 类

在传统JavaScript中类是基于原型模拟出来的类,在ES6中新增class关键字来书写基于类的面向对象(底层还是基于原型的方式)
类
维基百科 -> 在面向对象编程,类(英语:class)是一种面向对象计算机编程语言的构造,是创建对象的蓝图,描述了所创建的对象共同的属性和方法
- ES5中的模拟类:
function Fn1(name, age) {
this.name = name
this.age = age
}
Fn1.prototype = {
constructor: Fn1,
setAge: function(age) {
this.age = age
console.log(age)
}
}
- ES6中的类
class Fn1 {
constructor(name, age) {
this.name = name
this.age = age
}
setAge(age) {
this.age = age
console.log(age)
}
}
- TypeScript中的类
class Fn1 {
constructor(name: string, age: number) {
this.name = name
this.age = age
}
setAge(age: number): void{
this.age = age
console.log(age)
}
}
继承
在TypeScript里,我们可以使用常用的面向对象模式。 基于类的程序设计中一种最基本的模式是允许使用继承来扩展现有的类
class Fn1 {
constructor(name: string, age: number) {
this.name = name
this.age = age
}
setAge(age: number): void {
this.age = age
console.log(this.age)
}
}
class Fn2 extends Fn1{
constructor(name: string, age: number) {
this.name = name
this.age = age
}
}
let fn1 = new Fn2('mickey', 26)
fn1.setAge(27) // 27
继承我们可以通过关键字extends来继承
ES5中的继承方式推荐大家看一下阮一峰的博客构造函数的继承
public修饰符
C#要求必须明确地使用 public指定成员是可见的。 在TypeScript里,成员都默认为 public
class Fn1 {
public name: string
public constructor(name: string, age: number) {
this.name = name
this.age = age
}
public setAge(age: number): void {
this.age = age
}
}
private修饰符
当成员被标记成 private时,它就不能在声明它的类的外部访问
class Fn1 {
private name: string
public constructor(name: string, age: number) {
this.name = name
}
}
new Fn1().name // error 'name'是私有的
protected
protected修饰符与 private修饰符的行为很相似,但有一点不同, protected成员在派生类中仍然可以访问
class Fn1 {
protected name: string
constructor(name: string, age: number) {
this.name = name
}
}
class Fn2 extends Fn1{
constructor(name: string) {
super(name)
}
public getName() {
console.log(this.name)
}
}
new Fn2('mickey').name // error
new Fn2('mickey').getName() // mickey
我们不能在Fn1类外使用name,但是我们可以在派生出来的实例方法上使用name
readonly修饰符
你可以使用 readonly关键字将属性设置为只读的。 只读属性必须在声明时或构造函数里被初始化
class Fn1 {
readonly name: string
constructor(name: string) {
this.name = name
}
}
let f = new Fn2('mickey')
f.name = 'xxx' // error name是只读
参数属性
class Fn1 {
constructor(private name: string) { }
getName(): string {
console.log(this.name)
return this.name
}
}
上面代码我们通过在constructor参数private name: string来进行创建和初始化,我们就声明和赋值合并在一起了,public和 protected的使用也是一样
存取器
TypeScript支持通过getters/setters来截取对对象成员的访问。 它能帮助你有效的控制对对象成员的访问
let passcode = "secret passcode";
class Employee {
private _fullName: string;
get fullName(): string {
return this._fullName;
}
set fullName(newName: string) {
if (passcode && passcode == "secret passcode") {
this._fullName = newName;
}
else {
console.log("Error: Unauthorized update of employee!");
}
}
}
let employee = new Employee();
employee.fullName = "Bob Smith";
if (employee.fullName) {
alert(employee.fullName);
}
存取器要求你将编译器设置为输出ECMAScript 5或更高。 不支持降级到ECMAScript 3。 其次,只带有get不带有set的存取器自动被推断为 readonly。 这在从代码生成 .d.ts文件时是有帮助的,因为利用这个属性的用户会看到不允许够改变它的值
static修饰符
我们可以创建类的静态成员,这些属性存在于类本身上面而不是类的实例上
class Styles {
static width = 200
constructor(public style: object) {}
getWidth() {
console.log(Styles.width) // 200
}
}
new Styles({height: 200})
抽象类
抽象类做为其它派生类的基类使用。 它们一般不会直接被实例化。 不同于接口,抽象类可以包含成员的实现细节。 abstract关键字是用于定义抽象类和在抽象类内部定义抽象方法
abstract class Department {
constructor(public name: string) {
}
printName(): void {
console.log('Department name: ' + this.name);
}
abstract printMeeting(): void; // 必须在派生类中实现
}
class AccountingDepartment extends Department {
constructor() {
super('Accounting and Auditing'); // 在派生类的构造函数中必须调用 super()
}
printMeeting(): void {
console.log('The Accounting Department meets each Monday at 10am.');
}
generateReports(): void {
console.log('Generating accounting reports...');
}
}
let department: Department; // 允许创建一个对抽象类型的引用
department = new Department(); // 错误: 不能创建一个抽象类的实例
department = new AccountingDepartment(); // 允许对一个抽象子类进行实例化和赋值
department.printName();
department.printMeeting();
department.generateReports(); // 错误: 方法在声明的抽象类中不存在
上面我们介绍了TypeScript的类,第五节我们将介绍函数
文章参考TypeScript中文网
阮一峰Es6