面向对象
除了继承JS的所有特性外,TS还在编译阶段引入了类(class)、接口(interface)、泛型(generics)等语法糖,使我们更容易以面向对象的方式编写代码。
class(类)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| class Person{ name: string; private age: number; readonly sex: string; static eyeNum: number = 2; protected height: number; constructor(name,age,sex){ this.name = name; this.age = age; this.sex = sex; } getAge() { return this.age; } static sayHi(){ console.log("Hi!"); } } const per = new Person("abc",18,"male"); console.log(per.name); console.log(per.age); console.log(per.getAge()); console.log(Person.eyeNum); console.log(per.sex); per.sex = "female"; Person.sayHi()
|
1 2 3 4
| class animal{ constructer(public name: string,private age: number){} }
|
extends(继承)
使用extends关键字表示继承,格式为 class 子类 extends 父类{},子类将会拥有父类所有属性与方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| class animal { name: string; private age: number; constructer(name: string,age: number){ this.name = name; this.age = age; } sayHi(){ console.log("Hi!"); } getAge(){ return this.age; } } class dog extends animal{ weight: number; constructer(name, age, weight){ super(name, age); this.weight = weight; } satyHi(){ console.log("汪汪"); } } class cat extends animal{ sayHi(){ console.log("喵喵"); } } const dog1 = new dog("dog1",5,15); const cat1 = new cat("cat1",3); console.log(dog1.getAge()); dog1.sayHi(); cat1.sayHi();
|
abstract class(抽象类)
使用abstract关键字修饰class类,使之成为抽象类,抽象类具有以下特征:
- 不能用来创建对象,是专门用来被继承的类;
- 可以添加抽象方法,使用
abstract修饰方法;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| abstract class animal { name: string; constructor(name: string){ this.name = name; } abstract sayHello(): void; } class dog extends animal { sayHello(){ console.log("wangwang"); } } const dog1 = new dog("dog1"); const ani = new animal("ani"); dog1.sayHello();
|
interface(接口)
使用interface关键字声明接口,与普通的类型声明类似
1 2 3 4 5 6 7 8 9 10
| type myType = { name: string; }
interface myInterface { name: string; } const person1: myType ={name: "aaa"}; const person2: myInterface = {name:"bbb"};
|
但类型声明不能重复被声明,接口可以重复声明,两个接口的并集为最终的接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| type myType = { name: string; } type myType = { age: number; } interface myInterface { name: string; } interface myInterface { age: number; } const person1: myType ={ name: "aaa" }; const person2: myInterface = { name: "bbb"; age: 18; };
|
接口可以在定义类型的时候限制类的结构,只定义对象的结构,其中的属性不能有实际的值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| interface myInter{ name: string; sayHello(): void; }
class person implements myInter{ name: string; constructer(name){ this.name = name; } sayHello(){ console.log("Hello"); } }
|
属性的封装
属性可以被任意修改会导致对象中的数据变得非常不安全,使用封装可以保证数据的一致性与完整性
例如,一个 age 属性可能需要限制在 [0, 150] 之间,如果允许外部直接 person.age = -10,就会导致不合理的状态。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| class person { private age: number; constructer(age: number){ this.age = age; } getAge(){ return this.age; } setAge(value: number){ if(value>=0 && value<=150){ this.age = value } } get age(){ return this.age; } set age(value){ if(value>=0 && value<=150){ this.age = value } } } const per = new person(18);
console.log(per.getAge); console.log(per.setAge(20));
console.log(per.age) per.age = 20;
|
泛型
泛型可以使一个函数能处理多种不同类型的数据,并保证输入输出类型一致时
1 2 3 4 5
| function fn<T,K>(a: T,b: K): T{ return a; } fn(10); fn<string,number>("abc",123);
|
也可与接口结合使用
1 2 3 4 5 6
| interface IN{ length: number; } function fn<T extends IN>(a: T):number{ return a.length; }
|
定义类时也可使用泛型
1 2 3 4 5 6
| class person<T>{ name:T; constructer(name: T){ this.name = name; } }
|