TS 学习笔记(二)

342 阅读3分钟

类的定义与继承

// 如何定义类,如何在类中写属性和方法
class Person {
  name = "steven";
  getName() {
    return this.name;
  }
}
const person = new Person();
console.log(person.getName());

// 类的继承
class Teacher extends Person {
  getTeacher() {
    return "teacher";
  }
}
const teacher = new Teacher();
console.log(teacher.getName());
console.log(teacher.getTeacher());

// 类的重写:子类可以重写父类的属性
class Teacher1 extends Person {
  getName() {
    return "new name";
  }
  getTeacher() {
    return "teacher1";
  }
}
const teacher1 = new Teacher1();
console.log(teacher1.getName()); // output: "new name"

// super,当重写父类方法时可以调用父类方法
class Teacher2 extends Person {
  getName() {
    return super.getName() + "New name";
  }
}
const teacher2 = new Teacher2();
console.log(teacher2.getName()); // output: "stevenNew name"

类中的访问类型和构造器

// public, private, protected 访问类型
// public 允许在类的内外被调用,可省略不写,即默认为 public
// private 只允许在类内被使用
// protected 语序在类内及其继承的子类中使用

class Person {
  public name: string;
  private age: number;
  protected sex: string;
  public sayHi() {
    this.name; // public 属性 name 允许在类内被调用
    this.age; // private 属性 age 允许在类内被调用
    this.sex; // private 属性 age 允许在类内被调用
    console.log("hi");
  }
}
const person = new Person();
person.name = "steven"; // public 属性 name 允许在类外被调用
console.log(person.name);
person.sayHi();
person.age = 18; // private 属性 age 不允许在类外被调用
person.sex = "male"; // protected 属性 sex 不允许在类外被调用
class Teacher extends Person {
  public sayBye() {
    this.name; // public 属性 name 允许在子类中被调用
    this.age; // private 属性 age 不允许在子类中被调用
    this.sex; // protected 属性 sex 允许在子类中被调用
  }
}
// constructor
class Person {
  // 对类的属性进行初始化赋值
  // 传统写法
  // public name: string;
  // constructor(name: string) {
  //   this.name = name;
  // }
  // 简化写法
  constructor(public name: string) {}
}
const person = new Person("steven");
// 实例化一个类的时候,构造器在实例创建的时刻会自动被执行
console.log(person.name);

class Teacher extends Person {
  constructor(public age: number) {
    super("steven");
    // 父子继承时,如果子类用了构造器,则必须调用 super;即便父类没有构造器,也要调用空的 super 即 super()
  }
}
const teacher = new Teacher(28);
console.log(teacher.age);
console.log(teacher.name);

getter 和 setter

class Person {
  constructor(private _name: string) {}
  get name() {
    return this._name + " lee";
  }
  set name(name: string) {
    const realName = name.split(" ")[0];
    this._name = realName;
  }
}
const person = new Person("steven");
console.log(person.name); // 实际是调用其中的 get name,getter 的调用不需要加括号。output:'steven lee'

person.name = "steven lee"; // 调用了 set name,但是因为加工,realName实际存储的仍是 steven,保护 了私有属性
console.log(person.name); // 调用了 get name

// private 私有属性不能在类外被调用,可以通过 getter 的写法来实现外部调用
// 为了保证 private 属性的安全性,可以对数据进行加工,如 return this._name + " lee"
// 单例模式:对于一个类,只允许获取一个这个类的实例
// 以下为用 TS 实现方式
class Demo {
  private static instance: Demo;
  private constructor(public name: string) {}
  // 将构造器私有化,使得不能通过 new Demo() 来实例化
  static getInstance() {
    if (!this.instance) {
      this.instance = new Demo("steven");
    }
    return this.instance;
  }
  // static 静态属性,将方法挂在类上而不是类的实例上面
}

const demo1 = Demo.getInstance(); // new Demo() 然后 return
const demo2 = Demo.getInstance(); // 直接 return
// 实际上 demo1 === demo2

抽象类

// readonly
class Person {
  public readonly name: string;
  constructor(name: string) {
    this.name = name;
  }
}
const person = new Person("steven");
console.log(person.name);

// 抽象类 abstract class
// 将共用的部分抽离出来,形成抽象类
// 抽象类不能 new ,只能继承
abstract class Geom {
  width: string;
  getType() {
    return "Geom";
  }
  abstract getArea(): number; // 共用方法也可以抽象,但不写花括号实现
}
class Circle extends Geom {
  getArea() {
    return 100;
  }
}
class Square extends Geom {
  getArea() {
    return 200;
  }
}