学习地址:https://www.bilibili.com/video/BV1Xk4y127vb?p=3
抽象类
1.抽象类描述一种抽象的概念,无法被实例化,只能被继承
2.无法创建抽象类的实例
3.抽象方法不能在抽象类中实现,只能在抽象类的具体子类中实现,而且必须实现
/*** 抽象类 ,无法被实例化 ,* 子类继承以后,必须实现父类所有的方法* 要不就申明自身为一个抽象类* 抽象类也可以实现接口*/abstract class Animal{name:string;abstract getName():string;}class Cat extends Animal{getName(): string {return this.name;}}let cat =new Cat();cat.name='猫';
接口
1.接口一方面可以在面向对象编程中表示为行为的抽象,另外可以描述对象的形状(对象有哪些属性,属性是什么类型)
2.就是把一些类中共有的属性和方法抽象出来,可以用来约束实现此接口的类
3.一个类可以继承另一个类的并实现多个接口
4.接口像插件一样是用来增强类的,而接口类是具体类的抽象概念
5.一个类可以实现多个接口,一个接口也可以被多个类实现,但是一个类只能有一个父类,可以有多个父类
/*** 描述对象的结构* 申明接口可以用 分号 ,逗号,或者什么都不用*/interface Point {x: numbery: number}let point: Point = { x: 0, y: 0 }/*** 描述行为的抽象*/interface Speakable {speak(): void //因为接口里所有方法不能实现,只能放定义,所有的方法都是抽象的}interface Eatable {eat(): void}/*** 类可以实现多个接口,但是只能继承一个父类*/class Person extends Animal implements Speakable, Eatable {getName(): string { return '';}eat(): void { }speak(): void { }}
//任意属性interface PlainObject {[propName: string]: number;}namespace a {let obj: PlainObject = {x: 1,y: 2}}//接口的继承interface Speakable {speak(): void;}interface SpeakChinese extends Speakable {SpeakChinese(): void;}class Person implements SpeakChinese {SpeakChinese(): void { }speak(): void { }}//接口的readonlyinterface Circle {readonly PI: number;radius: number}let circle: Circle = {PI: 3.14,radius: 10}//接口还可以用来约束函数interface Discount {(price: number): string}let cost: Discount = function (price: number): string {return "";}//可索引接口//是用来对数组和对象进行约束的interface UserInterface {[index: number]: string}let arr: UserInterface = ['1', '2', '3'];let obj2: UserInterface = {1: '1',2: '2'}//类接口 可以用接口来装饰类 学ts核心 两个要素 接口和泛型interface Speakable {name: string,speak(words: string): void}class Dog implements Speakable {name: string;speak() { };}namespace c {//约束构造函数 类型,使用new来约束class Animal {constructor(public name: string) {}}interface WithNameClass {new(name: string): Animal;}//构造函数function createAnimal(clazz: WithNameClass, name: string) {return new clazz(name);}let c = createAnimal(Animal, '123');}
接口 vs 抽象类
重写override和重载overload
1.重写是指子类重写继承自父类的方法
2.重载是指同一函数提供多个函数的定义
重写在 子类中,重写父类的方法 ,在调用的时候就会调用子类的方法,要是还想调用父类,就得用super.方法调用 (super 在编译后 指的是父类的 prototype,并不是父类的原型或者申明的实例 ,super在constructor里值父类本身,在后面super调用方法的时候值得是 父类的prototype)
继承与静态没有关系,子类并不能继承父类的静态方法
泛型
1.指在定义函数、类或者接口的时候,不预先指定接口的类型,等到使用的时候在指定类型的特性
2.泛型T作用域只在函数内部
3.一般只有一个泛型的时候
//为什么会有泛型,它的意义在哪里namespace a{//定义函数function createArray<T>(length:number,val:T):Array<T>{let result:Array<T> =[];for(let i =0;i<length;i++){result[i]=val;}return result}let res=createArray<string>(3,'y');let res1=createArray<number>(4,4); //相当于一个参数//类数组 ArrayLike argments 和 domfunction sum (...args2:any[]){let args:IArguments = arguments;for(let i=0;i<args.length;i++){console.log(args[i])}}sum(1,2,'3',4);// let root:HTMLElement | null= document.getElementById('root');// let children:HTMLCollection= root.children;// let childNodes:NodeListOf<ChildNode> = root.childNodes;//泛型定义类class MyArray<T>{private list :T[]=[];add(val:T){this.list.push(val);}getMax():T {let reslut:T = this.list[0];for(let i=1;i<this.list.length;i++){if(this.list[i]>reslut){reslut=this.list[i];}}return reslut;}}let arr = new MyArray<number>();arr.add(1);arr.add(2);arr.add(10);let res2:number = arr.getMax();//接口的泛型interface Calculate {//接收泛型T然后 a,b 参数都是泛型类型的,然后参数返回值也是t<T>(a: T, b: T): T}//函数是接口类型的,然后定义函数let add: Calculate = function <T>(a: T, b: T): T {return a;}let res4 = add<number>(5, 5);//多个参数类型,如何在不增加中间变量的情况下,交换两个变量//利用泛型和元组function swap<A, B>(tuple: [A, B]): [B, A] {return [tuple[1], tuple[0]]}let res5 = swap<string, number>(['aaa', 10])//console.log(res5) [10,'aaa']//默认泛型类型 赋值一个默认值 ,但是就算是不给默认值ts也会根据传值类型自己去猜function createArray2<T = number>(length: number, val: T): Array<T> {let result: Array<T> = [];for (let i = 0; i < length; i++) {result[i] = val;}return result}let res6 = createArray2<string>(3, 'y');//泛型的约束//在函数中使用泛型的时候,由于预先并不知道具体类型,所以不能访问相应类型的方法//可以放泛型继承一个接口或者一个类interface LengthWise {length: number}function logger<T extends LengthWise>(val: T) {//即使你传参数的正确,依旧不可以这样使用 ,可以用接口约束一下,就可以调用了console.log(val.length);}logger("qasdas");//泛型接口,接口上放泛型interface Cart<T> {list: T[]}let cart: Cart<string> = {list: ['1', '2']}//泛型类型别名type Cart2<T> = { list: T[] } | T[];let c1: Cart2<string> = { list: ['1', '2'] };let c2: Cart2<string> = ['1', '2'];}
interface和 type的区别
interface 是接口类型,是定义一个接口,是一个真正的类型
type一般用来定义别名,并不是一个真正的类型,常用于联合类型
公共的用 interface 实现,不能用 interface 实现的再用 type 实现。主要是一个项目最好保持一致
使用’typeof 变量’,拿到变量的类型;
类型别名和字符串字面量类型都必须使用type进行定义
泛型接口 vs 类型别名
1.接口创建了一个 新的名字,他可以在任何地方被调用,而类型别名并不会创建名称,例如报错信息就不可以使用别名
2.类型别名不能被 extends 和 implements 这个时候我们要尽量使用接口代替 类型别名
3.当我们使用联合类型 和元组类型的时候 ,使用类型别名会更合适
