JavaScript语言基于函数与原型链继承的方式来构建可重用组件。对于OO编程来说会很奇怪,在下一代JavaScript标准(ES6)已经为我们提供OO设计方式。而TypeScript已经实现这种方式,无须等待ES6就可以放心的使用。

一、类

class Greeter {
    greeting: string; // public 属性
    constructor(message: string) { // 类构造函数
        this.greeting = message;
    }
    greet() { // public 方法
        return "Hello, " + this.greeting;
    }
}

// 使用new实例一个Greeter对象
var greeter = new Greeter("world");

和其他语言一样,我们可以在类方法里面使用 this 来代表当前实例的对象。

二、继承

OO编程最基本就是继承,先来看一个示例:

class Animal {
    name: string;
    constructor(theName: string) {
        this.name = theName;
    }
    move(meters: number = 0) {
        alert(this.name + ' moved ' + meters + 'm.');
    }
}

class Snake extends Animal {
    constructor(name: string) {
        super(name);
    }
    move(meters = 5) {
        alert('Slithering...');
        super.move(meters);
    }
}

class Horse extends Animal {
    constructor(name: string) {
        super(name);
    }
    move(meters = 45) { // 重写父类方法
        alert('Galloping...');
        super.move(meters); // 调用父类方法
    }
}

var sam = new Snake('Sammy the Python');
var tom: Animal = new Horse('Tommy the Palomino');

sam.move();
tom.move(34);

案例中和普通类只不过多了一个 extend 来表示类的继承关系,这和接口不同,只允许单一继承。

三、Private/Public 访问限制

在TypeScript中默认的访问限制为:public,这也就是为什么上面的案例都没有出现 public 字眼。如果想定义私有方法只须在方法前加:private。

class Animal {
    private name: string;
    constructor(theName: string) {
        this.name = theName;
    }
    say() {
        alert(this.name);
    }
}

四、参数属性

参数属性是访问限制另一种简单的写法,比如我们将上面案例改写成:

class Animal {
    constructor(private name: string) {
    }
    say() {
        alert(this.name);
    }
}

当我们在构造函数里声明一个带有 private 属性时,同时会自动将这个属性初始化成一个类私有属性。

五、属性访问器

在C#里,可以对某个属性的读和写(即:public string name { get; set; } )操作时执行语句。同样,TypeScript也有类似的实现方式。

class Employee {
    private _fullname: string;
    get fullname(): string {
        return this._fullname;
    }
    set fullname(newName: string) {
        // 做点其它的
        this._fullname = newName;
    }
}

var employee = new Employee();
employee.fullname = "asdf";
alert(employee.fullname);

六、静态

通过 static 标记某个属性或方法,这和我其他语言的使用方法一样,其可见性都是为类级访问。

class Grid {
    constructor(public scale: number) { }
    static origin = { x: 0, y: 0 } // 静态属性
    static show() { // 静态方法
        alert('sho');
    }
    cal(point: { x: number; y: number; }) {
        var xDist = (point.x - Grid.origin.x);
        var yDist = (point.y - Grid.origin.y);
        return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale;
    }
}

var grid1 = new Grid(1.0);  // 1x scale
var grid2 = new Grid(5.0);  // 5x scale

alert(grid1.cal({ x: 10, y: 10 }));
alert(grid2.cal({ x: 10, y: 10 }));