学习地址:https://www.bilibili.com/video/BV1Xk4y127vb?p=3

抽象类

1.抽象类描述一种抽象的概念,无法被实例化,只能被继承
2.无法创建抽象类的实例
3.抽象方法不能在抽象类中实现,只能在抽象类的具体子类中实现,而且必须实现

  1. /**
  2. * 抽象类 ,无法被实例化 ,
  3. * 子类继承以后,必须实现父类所有的方法
  4. * 要不就申明自身为一个抽象类
  5. * 抽象类也可以实现接口
  6. */
  7. abstract class Animal{
  8. name:string;
  9. abstract getName():string;
  10. }
  11. class Cat extends Animal{
  12. getName(): string {
  13. return this.name;
  14. }
  15. }
  16. let cat =new Cat();
  17. cat.name='猫';

接口

1.接口一方面可以在面向对象编程中表示为行为的抽象,另外可以描述对象的形状(对象有哪些属性,属性是什么类型)
2.就是把一些类中共有的属性和方法抽象出来,可以用来约束实现此接口的类
3.一个类可以继承另一个类的并实现多个接口
4.接口像插件一样是用来增强类的,而接口类是具体类的抽象概念
5.一个类可以实现多个接口,一个接口也可以被多个类实现,但是一个类只能有一个父类,可以有多个父类

  1. /**
  2. * 描述对象的结构
  3. * 申明接口可以用 分号 ,逗号,或者什么都不用
  4. */
  5. interface Point {
  6. x: number
  7. y: number
  8. }
  9. let point: Point = { x: 0, y: 0 }
  10. /**
  11. * 描述行为的抽象
  12. */
  13. interface Speakable {
  14. speak(): void //因为接口里所有方法不能实现,只能放定义,所有的方法都是抽象的
  15. }
  16. interface Eatable {
  17. eat(): void
  18. }
  19. /**
  20. * 类可以实现多个接口,但是只能继承一个父类
  21. */
  22. class Person extends Animal implements Speakable, Eatable {
  23. getName(): string { return '';}
  24. eat(): void { }
  25. speak(): void { }
  26. }
  1. //任意属性
  2. interface PlainObject {
  3. [propName: string]: number;
  4. }
  5. namespace a {
  6. let obj: PlainObject = {
  7. x: 1,
  8. y: 2
  9. }
  10. }
  11. //接口的继承
  12. interface Speakable {
  13. speak(): void;
  14. }
  15. interface SpeakChinese extends Speakable {
  16. SpeakChinese(): void;
  17. }
  18. class Person implements SpeakChinese {
  19. SpeakChinese(): void { }
  20. speak(): void { }
  21. }
  22. //接口的readonly
  23. interface Circle {
  24. readonly PI: number;
  25. radius: number
  26. }
  27. let circle: Circle = {
  28. PI: 3.14,
  29. radius: 10
  30. }
  31. //接口还可以用来约束函数
  32. interface Discount {
  33. (price: number): string
  34. }
  35. let cost: Discount = function (price: number): string {
  36. return "";
  37. }
  38. //可索引接口
  39. //是用来对数组和对象进行约束的
  40. interface UserInterface {
  41. [index: number]: string
  42. }
  43. let arr: UserInterface = ['1', '2', '3'];
  44. let obj2: UserInterface = {
  45. 1: '1',
  46. 2: '2'
  47. }
  48. //类接口 可以用接口来装饰类 学ts核心 两个要素 接口和泛型
  49. interface Speakable {
  50. name: string,
  51. speak(words: string): void
  52. }
  53. class Dog implements Speakable {
  54. name: string;
  55. speak() { };
  56. }
  57. namespace c {
  58. //约束构造函数 类型,使用new来约束
  59. class Animal {
  60. constructor(public name: string) {
  61. }
  62. }
  63. interface WithNameClass {
  64. new(name: string): Animal;
  65. }
  66. //构造函数
  67. function createAnimal(clazz: WithNameClass, name: string) {
  68. return new clazz(name);
  69. }
  70. let c = createAnimal(Animal, '123');
  71. }

接口 vs 抽象类

重写override和重载overload

1.重写是指子类重写继承自父类的方法
2.重载是指同一函数提供多个函数的定义
重写在 子类中,重写父类的方法 ,在调用的时候就会调用子类的方法,要是还想调用父类,就得用super.方法调用 (super 在编译后 指的是父类的 prototype,并不是父类的原型或者申明的实例 ,super在constructor里值父类本身,在后面super调用方法的时候值得是 父类的prototype)

继承与静态没有关系,子类并不能继承父类的静态方法

泛型

1.指在定义函数、类或者接口的时候,不预先指定接口的类型,等到使用的时候在指定类型的特性
2.泛型T作用域只在函数内部
3.一般只有一个泛型的时候 ,但是T可以是任意字母组合,随便写,但是最好有规范

  1. //为什么会有泛型,它的意义在哪里
  2. namespace a{
  3. //定义函数
  4. function createArray<T>(length:number,val:T):Array<T>{
  5. let result:Array<T> =[];
  6. for(let i =0;i<length;i++){
  7. result[i]=val;
  8. }
  9. return result
  10. }
  11. let res=createArray<string>(3,'y');
  12. let res1=createArray<number>(4,4); //相当于一个参数
  13. //类数组 ArrayLike argments 和 dom
  14. function sum (...args2:any[]){
  15. let args:IArguments = arguments;
  16. for(let i=0;i<args.length;i++){
  17. console.log(args[i])
  18. }
  19. }
  20. sum(1,2,'3',4);
  21. // let root:HTMLElement | null= document.getElementById('root');
  22. // let children:HTMLCollection= root.children;
  23. // let childNodes:NodeListOf<ChildNode> = root.childNodes;
  24. //泛型定义类
  25. class MyArray<T>{
  26. private list :T[]=[];
  27. add(val:T){
  28. this.list.push(val);
  29. }
  30. getMax():T {
  31. let reslut:T = this.list[0];
  32. for(let i=1;i<this.list.length;i++){
  33. if(this.list[i]>reslut){
  34. reslut=this.list[i];
  35. }
  36. }
  37. return reslut;
  38. }
  39. }
  40. let arr = new MyArray<number>();
  41. arr.add(1);
  42. arr.add(2);
  43. arr.add(10);
  44. let res2:number = arr.getMax();
  45. //接口的泛型
  46. interface Calculate {
  47. //接收泛型T然后 a,b 参数都是泛型类型的,然后参数返回值也是t
  48. <T>(a: T, b: T): T
  49. }
  50. //函数是接口类型的,然后定义函数
  51. let add: Calculate = function <T>(a: T, b: T): T {
  52. return a;
  53. }
  54. let res4 = add<number>(5, 5);
  55. //多个参数类型,如何在不增加中间变量的情况下,交换两个变量
  56. //利用泛型和元组
  57. function swap<A, B>(tuple: [A, B]): [B, A] {
  58. return [tuple[1], tuple[0]]
  59. }
  60. let res5 = swap<string, number>(['aaa', 10])
  61. //console.log(res5) [10,'aaa']
  62. //默认泛型类型 赋值一个默认值 ,但是就算是不给默认值ts也会根据传值类型自己去猜
  63. function createArray2<T = number>(length: number, val: T): Array<T> {
  64. let result: Array<T> = [];
  65. for (let i = 0; i < length; i++) {
  66. result[i] = val;
  67. }
  68. return result
  69. }
  70. let res6 = createArray2<string>(3, 'y');
  71. //泛型的约束
  72. //在函数中使用泛型的时候,由于预先并不知道具体类型,所以不能访问相应类型的方法
  73. //可以放泛型继承一个接口或者一个类
  74. interface LengthWise {
  75. length: number
  76. }
  77. function logger<T extends LengthWise>(val: T) {
  78. //即使你传参数的正确,依旧不可以这样使用 ,可以用接口约束一下,就可以调用了
  79. console.log(val.length);
  80. }
  81. logger("qasdas");
  82. //泛型接口,接口上放泛型
  83. interface Cart<T> {
  84. list: T[]
  85. }
  86. let cart: Cart<string> = {
  87. list: ['1', '2']
  88. }
  89. //泛型类型别名
  90. type Cart2<T> = { list: T[] } | T[];
  91. let c1: Cart2<string> = { list: ['1', '2'] };
  92. let c2: Cart2<string> = ['1', '2'];
  93. }

interface和 type的区别

interface 是接口类型,是定义一个接口,是一个真正的类型
type一般用来定义别名,并不是一个真正的类型,常用于联合类型
公共的用 interface 实现,不能用 interface 实现的再用 type 实现。主要是一个项目最好保持一致
使用’typeof 变量’,拿到变量的类型;
类型别名和字符串字面量类型都必须使用type进行定义

泛型接口 vs 类型别名

1.接口创建了一个 新的名字,他可以在任何地方被调用,而类型别名并不会创建名称,例如报错信息就不可以使用别名
2.类型别名不能被 extends 和 implements 这个时候我们要尽量使用接口代替 类型别名
3.当我们使用联合类型 和元组类型的时候 ,使用类型别名会更合适