一、类介绍
传统的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();//接口继承类中的定义不包含事项,使用接口调用编译出错