TypeScript - TypeScript 面向对象
一、面向对象概述面向对象是程序中一个非常重要的思想面向对象简而言之就是程序之中所有的操作都需要通过对象来完成举例来说操作浏览器需要使用 window 对象操作网页要使用 document 对象操作控制台要使用 console 对象计算机程序的本质就是对现实事物的抽象抽象的反义是具体比如汽车模型是对具体汽车的抽象程序也是对事物的抽象一个事物到了程序中就变成了一个对象在程序中一切皆是对象在程序中所有的对象都被分成两个部分即数据与功能以人为例姓名、性别、年龄、身高、体重等属于人的数据说话、走路、吃饭、睡觉等属于人的功能数据在对象中被成为属性功能被称为方法二、类1、基本介绍类可以理解为对象的模型程序中可以根据类创建指定类型的对象class【类名】{【属性名】:【类型】;constructor(【参数】:【类型】){this.【属性名】【参数】;}【方法名】(){}}2、基本使用classPerson{name:string;age:number;constructor(name:string,age:number){this.namename;this.ageage;}sayHello(){console.log(大家好我是${this.name});}}constpnewPerson(张三,18);p.sayHello();三、面向对象特点1、封装1基本介绍对象实质上就是属性和方法的容器它的主要作用就是存储属性和方法这就是封装默认情况下对象的属性是可以任意的修改的为了确保数据的安全性在 TS 中可以对属性的权限进行设置2基本使用readonly只读属性无法修改classPerson{readonlyname:string;readonlyage:number;constructor(name:string,age:number){this.namename;this.ageage;}sayHello(){// this.name 李四; // 类中无法修改console.log(大家好我是${this.name});}}classEmployeeextendsPerson{constructor(name:string,age:number){super(name,age);// this.name name; // 子类中无法修改}}letpnewPerson(张三,20);console.log(p.name);// 张三// p.name 李四; // 通过对象无法修改public默认值可以在类、子类和对象中访问与修改classPerson{publicname:string;publicage:number;constructor(name:string,age:number){this.namename;this.ageage;}sayHello(){this.name李四;// 类中可以修改console.log(大家好我是${this.name});}}classEmployeeextendsPerson{constructor(name:string,age:number){super(name,age);this.namename;// 子类中可以修改}}letpnewPerson(张三,20);p.name李四;// 通过对象可以修改console.log(p.name);// 李四protected可以在类、子类中访问与修改classPerson{protectedname:string;protectedage:number;constructor(name:string,age:number){this.namename;this.ageage;}sayHello(){this.name李四;// 类中可以修改console.log(大家好我是${this.name});}}classEmployeeextendsPerson{constructor(name:string,age:number){super(name,age);this.namename;// 子类中可以修改}}letpnewPerson(张三,20);// console.log(p.name); // 通过对象无法访问// p.name 李四; // 通过对象无法修改private只能在类中访问与修改classPerson{privatename:string;privateage:number;constructor(name:string,age:number){this.namename;this.ageage;}sayHello(){this.name李四;// 类中可以修改console.log(大家好我是${this.name});}}classEmployeeextendsPerson{constructor(name:string,age:number){super(name,age);// this.name name; // 子类中无法修改}}letpnewPerson(张三,20);// console.log(p.name); // 通过对象无法访问// p.name 李四; // 通过对象无法修改getter 与 setter对于一些不希望被任意修改的属性可以将其设置为 private并在类中定义一组读取getter、写setter属性的方法这种对属性读写的方法被称为属性存取器classPerson{private_name:string;constructor(name:string){this._namename;}getname(){returnthis._name;}setname(name:string){this._namename;}}letp1newPerson(孙悟空);console.log(p1.name);// 孙悟空通过 getter 读取 name 属性p1.name猪八戒;// 通过 setter 修改 name 属性console.log(p1.name);// 猪八戒static静态属性方法也称为类属性无需创建实例通过类即可直接使用静态属性classTools{staticPI3.14;staticsum(num1:number,num2:number){returnnum1num2;}}console.log(Tools.PI);// 3.14console.log(Tools.sum(123,456));// 579this在类中this 是当前对象2、继承通过继承可以将父类中的属性和方法引入到当前类中classAnimal{name:string;age:number;constructor(name:string,age:number){this.namename;this.ageage;}}classDogextendsAnimal{bark(){console.log(${this.name}在汪汪叫);}}constdognewDog(旺财,4);dog.bark();方法重写通过继承可以在不修改类的情况下完成对类的扩展即方法重写在子类中可以使用 super 来完成对父类的引用classAnimal{name:string;age:number;constructor(name:string,age:number){this.namename;this.ageage;}run(){console.log(父类中的 run 方法);}}classDogextendsAnimal{bark(){console.log(${this.name}在汪汪叫);}run(){console.log(子类中的 run 方法会重写父类中的 run 方法);}superRun(){super.run();}}constdognewDog(旺财,4);dog.bark();// ----------dog.run();// 子类中的 run 方法会重写父类中的 run 方法dog.superRun();// 父类中的 run 方法抽象类抽象类是专门用来被继承的类它只能被继承不能用来创建实例使用 abstract 关键字的方法是抽象方法抽象方法没有方法体且只能定义在抽象类中继承抽象类时抽象方法必须要实现abstractclassAnimal{abstractrun():void;bark(){console.log(动物在叫~);}}classDogextendsAnimal{run(){console.log(狗在跑~);}}四、接口1、基本介绍接口的作用类似于抽象类不同点在于接口中的所有属性和方法都是没有实体的即都是抽象的接口主要负责定义一个类的结构2、基本使用接口可以去限制一个对象对象只有包含接口中定义的所有属性和方法时才能匹配接口interfacePerson{name:string;sayHello():void;}functionfn(p:Person){p.sayHello();}fn({name:孙悟空,sayHello(){console.log(你好我是${this.name});},});// 你好我是孙悟空一个类可以去实现接口实现接口的类中要包含接口中定义的所有属性和方法interfacePerson{name:string;sayHello():void;}classStudentimplementsPerson{constructor(publicname:string){}sayHello(){console.log(你好我是${this.name});}}letsnewStudent(张三);s.sayHello();// 你好我是张三五、泛型1、基本介绍定义一个函数或类时有些情况下无法确定其中要使用的具体类型即参数的类型、返回值的类型、属性的类型无法确定此时可以泛型2、基本使用下例中test 函数参数类型不确定但是能确定的是其参数的类型和返回值的类型是相同的由于类型不确定所以参数和返回值均使用了 any但是这样做会关闭 TS 的类型检查其次也不能体现出参数和返回值是相同类型functiontest(arg:any):any{returnarg;}使用泛型// 方式一直接使用// 使用时可以直接传递参数类型会由 TS 编译器自动推断出来但有时编译器无法自动推断test(10);// 方式二指定类型// testnumber(hello); // 类型不符则报错testnumber(100);可以同时指定多个泛型使用逗号隔开functiondemoT,K(a:T,b:K):K{returnb;}demonumber,string(10,hello);在类中使用泛型classMyClassT{prop:T;constructor(prop:T){this.propprop;}}泛型范围约束下例中的泛型 T 必须是 MyInter 的子类interfaceMyInter{length:number;}classSelfInterimplementsMyInter{constructor(publiclength:number){}}functionrunTextendsMyInter(arg:T):number{returnarg.length;}console.log(runSelfInter(12345));// 5