美文网首页
02_TypeScript学习(二)

02_TypeScript学习(二)

作者: coderhzc | 来源:发表于2022-05-28 16:45 被阅读0次

    一. 认识类的使用:

    image.png

    二. 类的定义

    image.png
    //  TS类的基本定义
    class Person {
      name: string
      age: number
    
      eating() {
        console.log(this.name + "eating");
        
      }
    }
    export {}
     
    

    TS 在严格模式下要赋值

    image.png

    三. 一 类的继承

    image.png
    class Person {
      name: string
      age: number
      constructor(name: string, age: number) {
        this.name = name
        this.age = age
    
      }
      eating() {
        console.log('Person eating~');
      }
    }
    // 继承 学生 Student extends Person 
    class Student extends Person {
      sno: number
      constructor(name: string, age: number, sno: number) {
        // super调用父类的构造器
        super(name, age)
        this.sno = sno
      }
      /**
       * PS: 其实这个地方可以不写这个函数,直接去继承父类的eating函数,
       *     但是需求是: 我只想在我自己的类中写自己的处理逻辑,不想去继承父类的,
       *     这个时候就可以在自己类中重写一个eating方法,
       */
      eating() { 
        console.log('Student eating~');
      }
      studying() {
        console.log('studying');
      }
    }
    
    // 学生:
    const stu = new Student('huzhenchu', 18, 11);
    console.log(stu.name);
    console.log(stu.age);
    console.log(stu.sno);
    stu.eating() // 他的执行顺序是: 如果在自己的类中找不到eating方法就会去父类中去找,
    stu.studying() // 他的执行顺序是: 如果在自己的类中找不到studying方法就会去父类中去找,
    
    export { }
    
    

    三.二.需求:

    需求:如果你还想在执行自己类中的方法的时候,还想执行父类中的eating方法 那该咋办呢?

    class Person {
      name: string
      age: number
      constructor(name: string, age: number) {
        this.name = name
        this.age = age
      }
      eating() {
        console.log("我是Person 中的 eating");
    
      }
    }
    
    
    // 学生继承Person中的属性和方法
    class Student extends Person {
      sno: number
      constructor(name: string, age: number, sno: number) {
        super(name, age);// 这个super是调用父类的构造器
        this.sno = sno
      }
      studying() {
        console.log("studying");
    
      }
    
      // 如果子类不满意父类 Person中的eating方法的话,子类可以在自己的class 中重写eating方法的
      eating() {
        // 需求:如果你还想在执行自己类中的方法的时候,还想执行父类中的eating方法 那该咋办呢?
        super.eating()
        console.log("我是 student中的 eating方法");
    
      }
    }
    const stu = new Student("why", 18, 1111)
    console.log(stu.name);
    console.log(stu.age);
    console.log(stu.sno);
    
    stu.eating()
    
    
    export { }
    

    实际截图

    image.png

    三.三 类的多态

    animal.action // 他的执行顺序是: 如果在自己的类中找不到action方法就会去父类中去找,
    animal.action // 他的执行顺序是: 如果在自己的类中找不到action方法就会去父类中去找,

    class Animal {
      action() {
        console.log("animal running");
    
      }
    }
    
    class Dog extends Animal {
      action() {
        console.log("dog running !!!");
    
      }
    }
    
    class Fish extends Animal {
      action() {
        console.log("Fish swimming!!!");
    
      }
    }
    function makeActions(animals: Animal[]) {
      animals.forEach(animal => {
        animal.action(); // 他的执行顺序是: 如果在自己的类中找不到action方法就会去父类中去找,所以当前的action指向的当前各自类中的action方法
      })
    }
    
    makeActions([new Dog(), new Fish()]);
    export {}
    

    实际截图

    image.png

    四.类的成员修饰符

    image.png

    四.一 public修饰符

    /**
     * 1. public 修饰符 public 修饰的是在任何地方可见、公有的属性或方法,默认编写的属性就是public的;
     * 
     * 他可以在在类的内部访问,也可以在外面访问,取值和赋值都是可以的
     * **/ 
    class Person {
      public name: string = ""
    }
    
    const p = new Person()
    console.log(p.name);
    

    image.png

    四.二 类的成员修饰符-private修饰符的使用

    /**
     *  2. private 修饰的是仅在同一类中可见、私有的属性或方法;
     * 
     *     他只能在类的内部访问,在外面访问直接报错,取值和赋值都是不可以的
     * **/
    
    class Person1 {
      private name: string = "";
    
      // 如果你想获取Person1中的name的值得话 只能定义一个函数 然后让这个getName函数 在内部访问 这个name,最后在外部使用p1.getName()去调用获取到这个name值
      getName() { 
        return this.name
      }
    
      // 如果你想设置Person1中的name的值得话 只能定义一个函数 然后让这个setName函数 在内部访问 这个name,最后在外部使用p1.setName()去调用获取到这个name值
      setName() { 
        return this.name = "楚楚胡"
      }
    }
    
    const p1 = new Person1()
    // console.log(p1.name); // 所以这里是访问不到的,直接报错,
    console.log(p1.getName()); 
    console.log(p1.setName()); 
    
    export {}
    

    实际截图

    image.png

    四.三 07_类的成员修饰符-protected修饰符的使用

    // 3. protected 修饰的是仅在类自身和子类中可见、受保护的属性或方法;也就是说 在自己类的内部和子类继承中访问
    class Person {
      // protected 修饰的是仅在类自身及子类中可见、受保护的属性或方法;
      protected name: string = "123"
    }
    
    
    class Student extends Person {
      getName() {
        return this.name
      }
    }
    
    const stu = new Student()
    // console.log(stu.name); // 所以这里是访问不到的,直接报错,因为他 修饰的是仅在类自身及子类中可见
    
    console.log(stu.getName()); 
    
    export {} 
    

    实际截图

    image.png

    五. 只读属性readonly

    image.png
    class Person {
      // 1. 只读属性是在constcurtor中赋值的,赋值以后就不可以修改了
      // 2. 属性本身不能进行修改,但是如果他是对象类型, 对象的属性是可以修改的
      readonly name:string 
      readonly friend?:Person
      age?:number
      constructor(name:string,friend?:Person){
        this.name = name
        this.friend = friend
      }
    }
    
    const p = new Person ("huzhenchu",new Person("Kobe"))
    console.log(p.name)
    console.log(p.friend)
    // p.friend = new Person("Jamess");  // 只读属性 这里就不可以再做修改了
    
    if(p.friend) {
      p.friend.age = 30
    }
    

    实际截图

    image.png

    六. getters/setters

    image.png
    class Person {
      private _name: string // 私有属性
      constructor(name: string) {
        this._name = name
      }
    
      // 访问器setter/getters
      set name(newName) {
        this._name = newName
      }
    
      // getter
      get name() {
        return this._name
      }
    }
    
    const p = new Person("huzhenchu");
    // 设置属性
    p.name = "huzhenchu";
    
    // 获取
    console.log(p.name);
    

    实际截图

    image.png

    七.静态成员

    image.png
    // class Person {
    //   name:string =""
    //   age:number = 12
    
    // }
    // const p = new Person()
    // p.name = "123"
    
    /**
     *  1. static 类的静态属性 
     *  上面的那这种是要new Person 
     *  但是 我们使用 static 属性以后 可以直接去访问类里面的属性
     * 
     * 
     * **/
    class Student {
      static time: string = "20:00"
     static attendClass() {
        console.log("去学习~");
        
      }
    }
    
    console.log(Student.time);
    Student.attendClass()
    
    

    实际截图

    image.png

    八.抽象类abstract

    image.png
    // 1. 原始写法
    function makeArea(shape: any) {
      return shape.getArea()
    }
    //  计算矩形的面积
    class Reactangle {
      private width: number
      private height: number
      constructor(width: number, height: number) {
        this.width = width
        this.height = height
      }
      getArea() {
        return this.width * this.height
      }
    }
    const rectangle = new Reactangle(20, 30)
    console.log(rectangle); // { width: 20, height: 30 }
    
    console.log(makeArea(rectangle)); // 600
    
    
    //  计算圆形的面积
    class Circle {
      private r: number
    
      constructor(r: number) {
        this.r = r
      }
    
      getArea() {
        return this.r * this.r * 3.14
      }
    }
    
    const circle = new Circle(10);
    console.log(makeArea(circle)); // 314
    
    
    /*********************************************/
    // 2. 抽象类abstract
    function makeArea(shape: Shape) {
      return shape.getArea()
    }
    
    abstract class Shape {
      // 抽象类abstract
      abstract getArea()
    }
    // 计算矩形的面积
    class Reactangle extends Shape{
      private width: number
      private height: number
      constructor(width: number, height: number) {
        super()
        this.width = width
        this.height = height
      }
      getArea() {
        return this.width * this.height
      }
    }
    const rectangle = new Reactangle(20, 30)
    console.log(rectangle); // { width: 20, height: 30 }
    
    console.log(makeArea(rectangle)); // 600
    
    
    // 计算圆形的面积
    class Circle extends Shape {
      private r: number
    
      constructor(r: number) {
        super()
        this.r = r
      }
    
      getArea() {
        return this.r * this.r * 3.14
      }
    }
    
    const circle = new Circle(10);
    console.log(makeArea(circle)); // 314
    
    

    实际截图

    image.png

    九.抽象类演练

    image.png

    十. 类的类型

    image.png
    class Person {
      name: string = "123"
      eating(){}
    }
    
    const p = new Person();
    
    // 这种就叫做类的类型
    const p1: Person = {
      name: "chuchuhu",
      eating(){
        console.log("ahahah");
        
      }
    }
    
    // 实际用途
    function printPerson(p:Person) {
      console.log(p.name);
      
    }
    printPerson({name:"Kobe",eating:function(){}})
    export {}
    

    十一.接口的声明

    image.png
    // 1. 通过类型(type)别名 来声明对象类型
    type InfoType = { name: string, age: number }
    const info: InfoType = {
      name: "why",
      age: 18
    }
    // 2.另外一种方式声明对象类型: 接口interface
    interface InfoType {
      name: string
      age: number
    }
    
    const info: InfoType = {
      name: "why",
      age: 18
    }
    

    十二.可选属性

    image.png
    // 2.1 使用 interface定义的类型 --- 可选类型
    interface InfoType1 {
      name?:string
      age?:number
    }
    
    const info1:InfoType1 = {
      name:'chuchuhu', // 这些可写可不写
      age:28 //这些可写可不写
    }
    

    十三. 只读属性

    image.png

    十四. 索引类型

    image.png
    /**
     * 需求: 放到这个对象中的所有的 key 都时数字类型的,value都是字符串类型的
     *      
     * 
     * 
     * **/
    // 通过interface 来定索引类型
    interface IndexLanguge {
      [index: number]: string
    }
    const frontLanguage: IndexLanguge = {
      0: 'HTML',
      1: "CSS",
      2: "JavaScript",
      3: "Vue",
      aaa: "1111" // 这里会直接报错,因为这个地方定义的 key 不是数字类型, 所以会报错,必须严格按照interface定义的数据来
    }
    
    /**
     * Desc: 放到这个对象中的所有的 key 都是字符串类型的,value是number类型的
     * 
     * **/ 
    interface IlanguageYear {
      [name: string]: number
    }
    const languageYear:IlanguageYear = {
      "C": 1972,
      "Jave": 1995,
      "JavaScript": 1996,
      "TypeScript": 2014
    }
    
    

    实际截图

    image.png

    十五. 函数类型

    image.png
    // 1. 使用type定义类型
    type CalFn = (n1: number, n2: number) => number
    
    function calc(num1: number, num2: number, calcFn: CalFn) {
      return calcFn(num1, num2)
    }
    
    const add: CalFn = (num1, num2) => {
      return num1 + num2
    }
    
    console.log(calc(20, 30, add)); // 50
    
    

    实际截图

    image.png

    十六. 接口继承

    image.png
    interface ISwim {
      swimming: () => void
    }
    
    interface IFly {
      flying: () => void
    }
    
    
    interface IAction extends ISwim, IFly {
    
    }
    
    const action: IAction = {
      swimming() {
    
      },
      flying() {
        
      }
    }
    
    

    十七. 接口的实现

    image.png
    interface ISwim {
      swimming: () => void
    }
    
    interface IEat {
      eating: () => void
    }
    
    // 类实现接口
    class Animal {
      
    }
    
    // 继承: 只能实现单继承
    // 实现: 实现接口, 类可以实现多个接口
    class Fish extends Animal implements ISwim, IEat {
      swimming() {
        console.log("Fish Swmming")
      }
    
      eating() {
        console.log("Fish Eating")
      }
    }
    
    
    class Person implements ISwim {
      swimming() {
        console.log("Person Swimming")
      }
    }
    
    
    // 编写一些公共的API: 面向接口编程
    function swimAction(swimable: ISwim) {
      swimable.swimming()
    }
    
    // 1.所有实现了接口的类对应的对象, 都是可以传入
    swimAction(new Fish())
    swimAction(new Person())
    
    
    swimAction({swimming: function() {}})
    

    十八. 交叉类型

    image.png
    // 一种组合类型的方式: 联合类型
    type WhyType = number | string
    type Direction = "left" | "right" | "center"
    
    
    // 另一种组件类型的方式: 交叉类型
    type WType = number & string
    
    interface ISwim {
      swimming: () => void
    }
    
    interface IFly {
      flying: () => void
    }
    
    type MyType1 = ISwim | IFly
    type MyType2 = ISwim & IFly
    
    const obj1: MyType1 = {
      flying() {
    
      }
    }
    
    const obj2: MyType2 = {
      swimming() {
    
      },
      flying() {
        
      }
    }
    
    export {}
    
    
    

    十九. 交叉类型的应用

    image.png

    二十. interface和type区别

    image.png
    /**
     * 1. interface和type区别:
     *   -- interface 可以重复的对某个接口来定义属性和方法;
     *   -- 如果名字相同的话,相当于是直接给合并了
     * **/
    interface IFoo {
      name: string
    }
    
    interface IFoo {
      age: number
    }
    // 如果名字相同的话,相当于是直接给合并了
    interface IFoo {
      name: string
      age: number
    }
    
    const foo: IFoo = {
      age: 19,
      name: "why"
    }
    
    /**
     * 2. interface和type区别:
     *   -- 而type定义的是别名,别名是不能重复的;
     *   -- 重复定义的话 直接会报错
     * 
     * **/
    
    type IBar = {
      name: string
    }
    
    type IBar = {
      age: number
    }
    
    export {}
    

    实际截图

    image.png

    二十一.字面量赋值

    image.png
    interface IPerson {
      name: string
      age: number
      height: number
    }
    
    // 需求: 上面定义好了 类型,但是我想在下面这个对象中多增加一个 address字段, 此时是会直接报错的
    // const p: IPerson = {
    //   name: "hzc",
    //   age: 18,
    //   height: 1.88
    // }
    
    // 正确写法
    const info = {
      name: "hzc",
      age: 18,
      height: 1.88,
      address: "武汉市"
    }
    const p: IPerson = info
    
    function printInfo(info:IPerson) {}
    printInfo(p)
    

    相关文章

      网友评论

          本文标题:02_TypeScript学习(二)

          本文链接:https://www.haomeiwen.com/subject/zrniprtx.html