一、类介绍

传统的JavaScript程序使用函数和基于原型的继承来创建可重用的组件。

从ECMAScript 2015,也就是ECMAScript6开始,JavaScript程序员将能够使用类的面向对象方式。但TypeScript,允许现在就使用这些特性,不需要等到下个JavaScript版本,并且编译后的JavaScript可以在所有浏览器和平台上运行。

二、类定义,访问修饰符、存取器、静态成员

1.默认为public

在TypeScript中类的成员默认为public,这和C#中不相同

2.private

当成员被标记为private时,他舅不能在类的外部访问。

3.protected

protected修饰符用于指定成员在继承关系的派生类访问,当然本类也可以访问。

4.readonly

readonly指定属性为只读。只能在声明时或构造函数里面被初始化。

//readonely 修饰符可以将属性设置为只读,则必选在声明时或构造函数里被初始化。
class Octopus {
    readonly name: string;
    readonly numberOfLegs: number = 8;
    constructor(theName: string) {
        this.name = theName;
    }
}

let dad = new Octopus('Man with thr 8 strong legs.');
console.info(dad);
console.log(dad.name);
//dad.name='张三丰'; 编译出错,只读属性在外部不能赋值

5.参数属性

用于将属性的定义和复制结合,参数属性也可以指定访问修饰符。

//参数属性,可以使定义和初始化结合
class Animal {
    constructor(private name: string) { }
    move(distanceInMeters: number) {
        console.log(`${this.name} moved ${distanceInMeters}`);
    }
}
let tom = new Animal('Tom Cat');
tom.move(500);

6.选取器 geeters/setters

用于对属性的访问,更详细的控制

//TypeScript 支持getters/setters 控制对成员的访问.
let passcode = 'secret password';
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 = "Blob Smitch";
if (employee.fullName) {
    alert(employee.fullName);
}

7.静态属性 static

只能使用类名访问,在当前类中使用也是如此,这和C#中不相同

//静态属性,使用类名访问静态成员
//特别说明,在当前类中访问静态成员也需要加类名,这个C#中不太相同
class Grid {
    static origin = { x: 0, y: 0 };
    static StaticName: string = '张三丰';
    constructor(public scale: number) { }
    calculateDistanceFormOrigin(point: { x: number, y: number }) {
        let xDist = (point.x - Grid.origin.x);
        let yDist = (point.y - Grid.origin.y);
        return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale;
    }

}

let grid1 = new Grid(1.0);
let grid2 = new Grid(5.0);

console.log(grid1.calculateDistanceFormOrigin({ x: 10, y: 10 }));
console.log(grid2.calculateDistanceFormOrigin({ x: 10, y: 10 }));

三、类使用

1.继承 extends

基于面向对象设计中最基本的模式,允许使用继承来扩展现有的类。

class Animal {
    name: string;
    constructor(theName: string) {
        this.name = name;
    }
    move(distanceInMeters: number = 0) {
        console.log(`${this.name} moved ${distanceInMeters}m.`);
    }
}

class Snake extends Animal {
    constructor(name: string) {
        super(name);
    }
    move(distanceInMeters = 5) {
        console.log('Slithering...');
        super.move(distanceInMeters);
    }
}
class Horse extends Animal {
    constructor(name: string) { super(name); }
    move(distanceInMeters = 45) {
        console.log('Galloping...');
        super.move(distanceInMeters);
    }
}

let sam = new Snake('Sammy the Phthon');
let tom = new Horse('Tommy the Palomino');
sam.move();
tom.move(34);

2.抽象类 abstract

抽象类作为其他派生类的基类使用。它们一般不会被实例化。

不同于接口,抽象类可以包含成员的实现细节。

abstract关键词用于定义抽象类和在抽象类内部的抽象方法。

抽象发放不包含具体实现并且必须在派生类中实现。

abstract class Animal {
    abstract makeSound(): void;
    move(): void {
        console.log('roaming the earch...');
    }
}



3.构造函数

TypeScript里声明一个类的使用,实际上同时声明了很多东西。首先是类的实例的类型,也就是类类型。

//使用 typeof 获取类类型的变量或引用
class Greeter {
    static standardGreeting = 'Hello ,threre';
    greeting: string;
    greet() {
        if (this.greeting) {
            return `Hello, ${this.greeting}`;
        } else {
            return Greeter.standardGreeting;
        }
    }
}
let greeter1: Greeter;
greeter1 = new Greeter();
console.log(greeter1.greet());

//获取类类型的变量
let greeterMarker: typeof Greeter = Greeter;
greeterMarker.standardGreeting = 'Hey ,there!';
let greeter2:Greeter=new greeterMarker();
console.log(greeter1.greet());
console.log(Greeter.standardGreeting);



4.接口继承类

JavaScript的弱类型原因,在TypeScript中允许接口可以继承类,继承所在类的成员不包含实现。

class Point{
    x:number;
    y:number;

    [number:number]:any;
    static showInfo():void{
        console.log(`adasdf`);
    }
}
interface Point3d extends Point{
    z:number;
}
let point3:Point3d={
    x:1,
    y:2,
    z:3
};
console.info(point3);
//Point3d.showInfo();//接口继承类中的定义不包含事项,使用接口调用编译出错