typeScript中的面向对象编程学习心得

SOLID原则(设计模式的6大原则)

  • 单一职责原则(SRP):表明软件组件(函数、类、模块)必须专注与单一的任务(只有单一的职责)
  • 开/闭原则(OCP):对扩展开放, 对修改关闭
  • 里氏替换原则(LSP):对象应该可以是在不改变程序正确性的前提下被它的子类所替换.
  • 接口隔离原则(ISP):应该将非常大的接口拆分成一些小的更具体的接口,多个特定特定客户端接口要好于一个宽泛用途的接口
  • 依赖反转原则(DIP):依赖于一个抽象而不是一个实例

​ 由属性方法组成, 属性通常用来描述对象的特征, 方法通常用来描述对象的行为。

​ 其中有一个特殊的方法, 叫做构造方法(与java的构造方法一样, 但是重写构造方法有点麻烦),在通过new关键字创建一个类的实例的时候会被调用。

下面是一个简单的例子, 定义了两个类, 一个Person类和一个Email类

Person类: 三个属性, 两个方法

import {Email} from './email';
export class Person {
  public name : string;
  public surname : string;
  public email : Email;
  constructor(name, surname, email) {
    this.name = name;
    this.surname = surname;
    this.email = email;
  }
  greet() {
    alert('Hi');
  }
}

下面是Email类

export class Email {
  private email : string;
  constructor(email) {
    if (this.validateEamil(email)) {
      this.email = email;
    } else {
      throw new Error("invalid email!");
    }
  }
  private validateEamil(email) {
    let re = /\S+@\S+\.\S+/;
    return re.test(email);
  }
}

两个类在文件中的位置关系

在这里插入图片描述

这样子写是为了符合单一职责原则, 如果这样写不符合单一职责原则

export class Person {
  public name : string;
  public surname : string;
  public email : Email;
  constructor(name, surname, email) {
    this.name = name;
    this.surname = surname;
    if (this.validateEamil(email)) {
      this.email = email;
    } else {
      throw new Error("invalid email!");
    }
  }
  validateEamil(email) {
    let re = /\S+@\S+\.\S+/;
    return re.test(email);
  }
  greet() {
    alert('Hi');
  }
}

因为validateEamil方法是和Person类的行为并无关联

继承

​ 可以扩展已有的类,这个功能被称为继承,允许我们创建一个类(子类), 从已有的类(父类)上继承所有的属性和方法,子类还可以包含父类中没有的属性和方法。但是值得注意的是,一个子类只能继承一个父类,不能继承多个父类,没有多重继承。

可以看下面的一个例子, 还是用上面提到的Person类和Email类

Person类:

import {Email} from './email';
export class Person {
  public name : string;
  public surname : string;
  public email : Email;

  constructor(name: string, surname: string, email: Email) {
    this.name = name;
    this.surname = surname;
    this.email = email;
  }
  greet() {
    console.log('Hi');
  }
}

Email类:

export class Email {
  private email : string;
  constructor(email) {
    if (this.validateEamil(email)) {
      this.email = email;
    } else {
      throw new Error("invalid email!");
    }
  }
  private validateEamil(email) {
    let re = /\S+@\S+\.\S+/;
    return re.test(email);
  }
}

现在用Teacher类继承Person类, Teacher类可以有父类没有的属性和方法, 也可以重写父类已经有的方法

Teacher类:

import {Person} from './person';
import {Email} from './email';

export class Teacher extends Person{

  public subject: string[];

  constructor(name: string, surname: string, email: Email, subject: string[]) {
    super(name, surname, email);
    this.subject = subject;
  }

  greet() {
    super.greet();
    console.log('我教 ' + this.subject);
  }
  teach() {
    console.log('我是老师, 我教学生');
  }
}

也可以有一个类继承Teacher类, 那么这个类会继承Teacher类中的所有方法和属性, 也会继承Person中的所有属性和方法

import {Teacher} from './teacher';
import {Email} from './email';

export class SchoolPrincipal extends Teacher{

  constructor(name: string, surname: string, email: Email, subject: string[]) {
    super(name, surname, email, subject);
  }

}

//运行下面代码
    let schoolPrincipal = new SchoolPrincipal("name", "surname", email, ["name1", "name2"]);
    schoolPrincipal.greet();
    schoolPrincipal.teach();

但是这里Person和Teacher都有greet()方法,当调用greet方法时,调用的是Teacher的greet方法,可以得出结论:

  • 父类(和父类的父类)有相同的方法的时候,调用直接继承父类的方法

猜你喜欢

转载自blog.csdn.net/hzjanger/article/details/84110428
今日推荐