类的声明 & 实现
TS为成员属性和构造函数的参数添加了类型注解 run方法默认返回值是void
class Dog {constructor(name: string) {this.name = name;}name: string;run() {}}

构造函数的返回值类型默认会被推断为Dog,即本类
注:
无论是在ES还是TS中,类的成员属性都是实例属性(而不是原型属性),类的成员方法都是原型方法
打印类的原型,查看是否包含内部属性
console.log(Dog.prototype);

类的原型不包含内部属性,原型上只有 run 方法和 constructor 构造方法
创建一个实例,并且输出
class Dog {constructor(name: string) {this.name = name;}name: string;run() {}}console.log(Dog.prototype);let dog = new Dog("wangcai");console.log(dog);

可以看到,内部属性 name 只在实例上,而不在原型上
异同点:
- 在TS实例的属性必须有初始值,或在构造函数中被初始化
- 如删掉构造函数中对name的初始化,将提示错误
- 如下代码所示:
```typescript
class Dog {
constructor(name: string) {
} name: string; run() {} }// this.name = name;
console.log(Dog.prototype);
let dog = new Dog(“wangcai”); console.log(dog);
<br />处理:```typescript// 初始值{class Dog {constructor(name: string) {// this.name = name;}name: string = "Dog";run() {}}console.log(Dog.prototype);let dog = new Dog("wangcai");console.log(dog);}// 可选属性{class Dog {constructor(name: string) {// this.name = name;}name?: string;run() {}}console.log(Dog.prototype);let dog = new Dog("wangcai");console.log(dog);}
总结:只要内部属性有初始值,就不会报错
继承
类的继承使用了extends关键字 类的构造函数constructor中调用了super,代表父类实例 父类Dog的构造函数中有一个参数name,所以子类也必须要有具有此参数
// 继承class Husky extends Dog {constructor(name: string, color: string) {super(name);this.color = color;}color: string;}
成员修饰符
类的成员修饰符部分是TS对ES所做的扩展
公有成员-public
类的所有属性默认均为public,表示对所有人可见
class Dog {constructor(name: string) {this.name = name;}public name: string;run() {}}
私有成员-private
私有成员,只能在类的本省调用,而不能被类的实例调用,也不能被子类调用
class Dog {constructor(name: string) {this.name = name;}public name: string;// name: string = 'dog'run() {}// 私有成员,只能在类的本省调用,而不能被类的实例调用,也不能被子类调用private pri() {}}let dog = new Dog("wangwang");console.log(dog); // Dog {legs: 4, name: "wangwang"}dog.pri();

私有成员也不能在子类中被调用
类的构造函数也可以被设置为私有成员,既不能被实例化也不能被继承了
// 类class Dog {private constructor(name: string) {this.name = name;}public name: string;run() {}private pri() {}}let dog = new Dog("wangwang");class Husky extends Dog {constructor(name: string, public color: string) {super(name);this.color = color;}}
受保护成员-protected
受保护成员,只能在类或者子类访问与调用,而不能在类的实例访问
// 类class Dog {constructor(name: string) {this.name = name;}public name: string;run() {}private pri() {}protected pro() {}}let dog = new Dog("wangwang");dog.pro();// 继承class Husky extends Dog {constructor(name: string, public color: string) {super(name);this.color = color;this.pro();}// color: string;}

构造函数也可以被声明为 protected,使这个类只能被继承,不能被实例化,相当于声明了一个基类
// 类class Dog {protected constructor(name: string) {this.name = name;}public name: string;run() {}private pri() {}protected pro() {}}let dog = new Dog("wangwang");// 继承class Husky extends Dog {constructor(name: string, public color: string) {super(name);this.color = color;this.pro();}// color: string;}
只读属性-protected
只读属性,这个属性不能被更改,而且不能被更改 和实例属性一样,类的只读属性必须被初始化
// 类class Dog {constructor(name: string) {this.name = name;}public name: string;run() {}private pri() {}protected pro() {}readonly legs: number = 4;}let dog = new Dog("wangwang");console.log(dog); // Dog {legs: 4, name: "wangwang"}
静态成员-static
类的静态成员只能通过类名来调用,不能通过子类来调用 类的静态成员可以被继承
// 类class Dog {constructor(name: string) {this.name = name;}public name: string;run() {}private pri() {}protected pro() {}readonly legs: number = 4;static food: string = "bones";}let dog = new Dog("wangwang");console.log(dog.food);console.log(Dog.food); // bones// 继承class Husky extends Dog {constructor(name: string, public color: string) {super(name);this.color = color;this.pro();}}console.log(Husky.food); // bones
构造函数的参数添加修饰符
除了类的成员可以添加修饰符外,构造函数的参数也可以添加修饰符 作用:将参数自动变成实例的属性,这样就可以省略在类中的定义
// 类class Dog {constructor(name: string) {this.name = name;}public name: string;run() {}private pri() {}protected pro() {}readonly legs: number = 4;static food: string = "bones";}// 继承class Husky extends Dog {constructor(name: string, public color: string) {super(name);this.color = color;this.pro();}color: string;}
抽象类的定义
抽象类只能被继承,不能被实例化 定义抽象类使用abstract关键字
abstract class Animal { }let animal = new Animal();
抽象类的继承
继承抽象类,需要在子类中调用super方法
abstract class Animal {eat() {console.log("eat");}}class Dog extends Animal {constructor(name: string) {super();this.name = name;}name: string;run() {}}let dog = new Dog("wangwang");console.log(dog.name);
抽象类实现方法复用
在抽象类中可以定义方法(可以有具体实现,也可以是抽象方法),从而实现复用 抽象类可以抽离事物的共性,有利于代码的复用和扩展
abstract class Animal {eat() {console.log("eat");}abstract sleep(): void;}class Dog extends Animal {constructor(name: string) {super();this.name = name;}name: string;sleep() {console.log("Dog sleep");}}let dog = new Dog("wangwang");dog.eat();dog.sleep();class Cat extends Animal {sleep() {console.log("Cat sleep");}}let cat = new Cat();cat.eat();cat.sleep();
抽象类实现多态
通过在父类中定义抽象方法,在不同子类中对该方法进行不同实现, 从而在运行时根据不同子类对象表现为不同状态
abstract class Animal {eat() {console.log("eat");}abstract sleep(): void;}class Dog extends Animal {constructor(name: string) {super();this.name = name;}name: string;sleep() {console.log("Dog sleep");}}let dog = new Dog("wangwang");dog.eat();dog.sleep();class Cat extends Animal {sleep() {console.log("Cat sleep");}}let cat = new Cat();cat.eat();cat.sleep();let animal: Animal[] = [dog, cat];animal.forEach((i) => {i.sleep();});
this类型
类的成员方法可以直接返回一个this,方便实现链式调用,即Builder模式
class WorkFlow {step1() {return this;}step2() {return this;}}new WorkFlow().step1().step2();
使用this实现多态
this代表实例本身,继承时,子类实例即可表现多态(this既可以是父类,也可以是子类)
class WorkFlow {step1() {return this;}step2() {return this;}}new WorkFlow().step1().step2();class Myflow extends WorkFlow {next() {return this;}}new Myflow().next().step1().next().step2();
接口对类的约束作用
接口能够对类的成员属性和类型进行约束(且只能约束类的公有成员) 注意: 类必须实现接口中声明的全部属性和方法 类可以新增独有的属性和方法
interface Human {// new(name: string): voidname: string;eat(): void;}// 类实现接口的时候,必须实现接口所有声明的属性// 接口只能约束类的共有成员// 接口不能约束构造函数class Asion implements Human {constructor(name: string) {this.name = name;}name: string;eat() {}sleep() {}}
接口继承
接口和类一样,可以相互继承,且一个接口可以继承多个接口 接口的继承特性可以将可重用部分进行抽离,也可以将多个接口合并成一个接口
interface Human {// new(name: string): voidname: string;eat(): void;}// 类实现接口的时候,必须实现接口所有声明的属性// 接口只能约束类的共有成员// 接口不能约束构造函数class Asion implements Human {constructor(name: string) {this.name = name;}name: string;eat() {}sleep() {}}// 接口继承interface Man extends Human {run(): void;}// 具有另外行为的接口interface Child {cry(): void;}// 多个接口组合使用interface Boy extends Man, Child {}// 属性与方法let boy: Boy = {name: "",run() {},eat() {},cry() {},};
接口继承类
接口除了可以继承接口外,还可以继承类,相当于将类成员全部抽象出来,仅有类的结构而没有具体实现 注意: 接口抽离类成员时,不仅抽离了公共成员,也抽离了私有成员和受保护成员
class Auto {state = 1;// private state2 = 0;}interface AutoInterface extends Auto {}class C implements AutoInterface {state = 1;}



class Auto {state = 1;// private state2 = 0;protected state3 = 3;}interface AutoInterface extends Auto {}class C implements AutoInterface {state = 1;// private state2 = 2;protected state3 = 3;}class Bus extends Auto implements AutoInterface {}
