首页 前端知识 TypeScript基础篇 - TS类【Class】

TypeScript基础篇 - TS类【Class】

2024-05-10 08:05:54 前端知识 前端哥 874 686 我要收藏

目录

Class的基础

Class 的定义

重载

成员函数的重载

Getter/Setter

索引器

组合和继承

类的继承

推荐使用组合或者泛型

成员

类的成员可见域

静态成员【static】

类型的相等

类型守卫【ts做窄化】

抽象类

TS的类型一致(所谓的子类可以赋值给父类)

小结


Class的基础

Class 的定义

class Point {
    // ts得先声明一下
    x: number
    y:number
    constructor(x: number, y: number) {
        this.x = x
        this.y = y    
    }
    public add(p: Point) : Point {
        return new Point(p.x + this.x, p.y + this.y)    
    }
}
const p = new Point(0, 0)
const newP = p.add(new Point(1, 1))
console.log(newP)

重载

成员函数的重载

class Point4 {
  // ts得先声明一下
  x: number
  y: number
  constructor(x: number, y: number) {
    this.x = x
    this.y = y
  }
  // class中对成员函数进行重载
  public add(x: number, y: number): Point;
  public add(p: Point): Point;
  public add(x: number | Point, y?: number) {
    if (typeof x === 'number') {
        // 因为y是可选项,所有y: number | undefined;写作有!,
        // 让null和undefined可以赋值给其他类型并通过编译
      return new Point4(this.x + x, this.y + y!)
    }
    const p = x
    return new Point4(this.x + p.x, this.y + p.y)
  }
}
const p4 = new Point4(0, 0)
const newP4 = p4.add(new Point4(1, 1))
console.log(newP4)

Getter/Setter

class C {
    _length = 0;
    // ES6语义
    get length() {
        return this._length;    
    }
    set length(value) {
        this._length = value;    
    }
}
class C {
    _length = 0;
    // 函数语义
    getLength() {
        return this._length;    
    }
    setLength(value) {
        this._length = value;    
    }
}

索引器

class Arr<T> {
    [i: number]: T // 索引器+类型标注
}
const a = new Arr<number>() // 索引器这个能力可以当成一个数组用,但是不常见
a[10] = 100
console.log(a[10]) // 100

组合和继承

类的继承

class Animal {
    move() {
        console.log("Moving along!");    
    }
}
class Dog extends Animal{ // 继承,重度耦合;Dog.move
    woof(times: number) {
        for(let i = 0; i < times; i++) {
            console.log("woof!");        
        }    
    }
}

推荐使用组合或者泛型

interface Movable { // 接口
    move() : void;
}
class Dog implements Movable { // 组合
    move() {
        console.log("move dog")    
    }
}
class Movable<T extends Animal> { // 泛型
    animal:T
    move() {
        console.log(`${animal.getName()} is moving`)    
    }
}

成员

类的成员可见域

  • public公开属性
  • protected保护属性
  • private私有属性
class Point { 
    public x: number // public
}
// x可以被任意程序访问
class Point {
    private x : number
    constructor() {
        this.x = x // 成立,x是私有的,只有自己的类里面可以用    
    }
    getX() {
        return this.x    
    }
}
const p = new Point()
console.log(p.x) // Error x是私有属性,只有在Point类里面可以用
console.log(p.getX()) // ok
class Animal {
    private _name1;
    protected _name2;
}
class Dog extends Animal {
    getName1(){
        return this._name1 // Error 继承类也不能访问私有属性
    }
    getName2(){
        return this._name2 // pass 继承类可以访问保护属性
    }
}

静态成员【static】

class MyClass {
    static x = 0; //静态成员
    static printX() {
        console.log(MyClass.x);    
    }
    static name = "S!"// Error name是静态成员的保留字,所以用不了
}
console.log(MyClass.x);
MyClass.printX();

类型的相等

类型守卫【ts做窄化】

class FileSystemObject { // 文件系统的对象
    isFile(): this is FileRep { // 守卫:文件类型断言,触发类型窄化
        return this instanceof FileRep;    
    }
    isDirectory(): this is Directory {// 守卫:目录类型断言,触发类型窄化
        return this instanceof Directory;    
    }
    isNetworked(): this is Networked & this {// 守卫:域名类型断言,触发类型窄化
        return this.networked;    
    }
    constructor(public path: string, private networked: boolean) {}
}
class FileRep extends FileSystemObject {
    constructor(path: string, public content: string) {
        //super()相当于FileRep.prototype.constructor.call(this)
        super(path, false)            
    }
}
class Directory extends FileSystemObject {
    children: FileSystemObject[];
}
const fso: FileSystemObject = new FileRep("foo/bar.txt", "foo");
is(fso.isFile()) { // 文件
    fso.content;
    // const fso: FileRep
} else if (fso.isDirectory()) { // 目录
  fso.children;
  // const fsoL:Directory  
} else if (fso.isNetworked()) { // 地址
    fso.host;
    // const fso:Networked & FileSysremObject
}

抽象类

如果抽象类中没有具体方法,全都是抽象方法,那就等价于interface接口

abstract class Base { // 抽象类 TS独有,JS中没有
// 抽象类不能实例化,只能继承
  abstract getName(): string;
  printName() {
    console.log("Hello," + this.getName());
  }
}
// 无法创建抽象类的实例
const b = new Base();
class Derived extends Base {
    // 继承抽象类,要实现一下继承过来的抽象类中的抽象方法 abstract getName()
    getName() {
        return "world";    
    }
}
const d = new Derived();
d.printName();

TS的类型一致(所谓的子类可以赋值给父类)

class Point1 {
    x = 0;
    y = 0;
}
class Point2 {
    x = 0;
    y = 0;
}
// OK 对于typescript来说,相同的结构,就是同一类型,
// TS检查,发生在编译时,做静态类型检查,看的就是静态成员是否一致
const p : Point1 = new Point2(); 
class Person {
    name: string;
    age:number;
}
class Employee {
    name: string;
    age:number;
    salary: number;
}
// OK TS是按成员来分辨是否是继承,像上面这种,TS认为是隐形的继承
// Employee比Person多一个成员,认为 class Employee extends Person {}
const p: Person = new Employee();

小结

  • TS如何判断类型的一致?代价如何?基于实际的每一项成员是否一致判断的。代价可以承担,就是慢点,而且发生在编译时。真正运行时,是不会有ts代码的,也不会帮我们生成新的代码不占我们的性能
  • 在Class的使用中,TS有实现JS没有的能力吗?没有,去掉ts部分依然可以运行,ts只有少量的是js没有的,如枚举
转载请注明出处或者链接地址:https://www.qianduange.cn//article/7866.html
标签
评论
会员中心 联系我 留言建议 回顶部
复制成功!