ts中的接口(interface)示例代码及解释

2023-12-29 20:30:39

目录

什么是interface

示例代码

函数接口

通过接口(interface)来约束函数的基本使用

通过接口约束函数参数为函数类型

class接口

通过抽象类实现

抽象类和接口的区别

构造函数接口

接口的继承

接口继承接口

接口继承类


什么是interface

在 TypeScript 中,interface(接口)是一种用来描述对象形状的结构化类型。与其他语言中的接口概念类似,它定义了对象应该具有的属性和方法,但不提供具体的实现。与类相似,接口可以扩展其他接口,并且可以用于描述函数类型、数组类型等数据形态。在 TypeScript 中接口非常常用,因为它可以帮助开发人员更好地理解代码和规避错误,提高代码的可维护性和可读性。

示例代码
interface Person {
    name: string;
    age: number;
}

const person: Person = {
    name: 'Tom',
    age: 18
};

定义了一个 Person 接口,它描述了一个拥有 name 和 age 属性的对象类型。我们可以将 person 对象的类型声明为 Person,并且确保它遵循了接口的结构。这样,在类型检查阶段,如果我们尝试为 person 对象赋值一个不符合接口的结构,就会在编译时期报错。

函数接口

在 TypeScript 中,我们可以使用接口来定义函数的类型。函数接口描述了函数的参数类型、返回值类型以及函数本身的结构。通过使用函数接口,我们可以对函数进行类型检查和约束。

通过接口(interface)来约束函数的基本使用
interface MathFunc {
  (x: number, y: number): number;
}

const add: MathFunc = (a, b) => {
  return a + b;
};

const multiply: MathFunc = (a, b) => {
  return a * b;
};

上面的代码定义了一个?MathFunc?函数接口,它描述了接受两个?number?类型的参数并返回?number?类型的函数。然后,我们可以使用该接口类型来声明变量?add?和?multiply,并实现函数的定义。在变量声明时,我们需要确保函数的结构与函数接口的描述一致,这样就可以进行类型检查和约束。

通过接口约束函数参数为函数类型
interface searchFunction {
  (kw:string, pgae?:number): string[]
}

interface saveFunction {
  (data:object):void
}
  
const searchAndSave = function(kw:searchFunction, save:saveFunction) {
  // code
}

searchAndSave((kw:string) => {
  return ['a', 'b', 'c']
}, () => {})

`searchFunction` 描述了一个接受一个字符串类型的关键字参数 `kw` 和一个可选的数字类型的页码参数 `page`,返回一个字符串数组类型的函数。

`saveFunction` 描述了一个接受一个对象类型的参数 `data`,没有返回值的函数。

接下来,通过 `searchAndSave` 函数,将这两个函数接口作为参数进行组合。`searchAndSave` 函数接受一个参数 `kw`,它是一个符合 `searchFunction` 函数接口的函数,并且接受一个参数 `save`,它是一个符合 `saveFunction` 函数接口的函数。在 `searchAndSave` 函数的实现中,可以根据需要使用这两个参数进行相应的操作。

在代码示例的最后一行,调用了 `searchAndSave` 函数,并传入了两个匿名函数作为参数。

第一个匿名函数 `kw => ['a', 'b', 'c']` 符合 `searchFunction` 函数接口的定义,它接受一个字符串参数 `kw`,并返回一个字符串数组。

第二个匿名函数 `() => {}` 是一个空函数,没有实现任何功能,但它符合 `saveFunction` 函数接口的定义,它接受一个对象参数 `data`,没有返回值。

通过这种方式,我们可以在调用 `searchAndSave` 函数时,根据业务需求传入相应的函数,并保证它们的参数和返回值类型的一致性。

class接口

在 TypeScript 中,我们可以使用接口来描述类的结构和约束类的属性和方法。这种接口常被称为类接口(class interface)或者构造函数接口(constructor interface)。

类接口主要用于定义类的实例部分的属性和方法。通过定义类接口,我们可以对类的实例进行类型检查和约束。

interface Point {
  x: number;
  y: number;
  move(dx: number, dy: number): void;
}

class MyPoint implements Point {
  x: number;
  y: number;

  constructor(x: number, y: number) {
    this.x = x;
    this.y = y;
  }

  move(dx: number, dy: number) {
    this.x += dx;
    this.y += dy;
  }
}

const point = new MyPoint(1, 2);
point.move(3, 4);
console.log(point.x, point.y);  // 输出: 4, 6

我们定义了一个类接口?Point,它描述了一个具有?x?和?y?属性,以及一个用于移动坐标的?move?方法的类。然后,我们创建了一个类?MyPoint,该类实现了?Point?接口。

在?MyPoint?类中,我们需要确保类的实例具有?x?和?y?属性,并实现了?move?方法的定义。通过实现接口,我们可以在编译时检查类的实例是否符合接口的要求。

最后,我们创建了一个?MyPoint?类的实例?point,并进行了一次坐标的移动。我们可以看到,通过类接口的约束,我们可以更好地对类的结构进行定义和约束。

通过抽象类实现

抽象类是一种特殊的类,它不能直接被实例化,而是用于作为其他类的基类(父类)。抽象类可以包含抽象方法和非抽象方法,并且可以提供一些基本的实现,让子类来继承和扩展。

abstract class Point {
  abstract x: number;
  abstract y: number;
  
  abstract move(dx: number, dy: number): void;
}

class MyPoint extends Point {
  x: number;
  y: number;

  constructor(x: number, y: number) {
    super();
    this.x = x;
    this.y = y;
  }

  move(dx: number, dy: number) {
    this.x += dx;
    this.y += dy;
  }
}

const point = new MyPoint(1, 2);
point.move(3, 4);
console.log(point.x, point.y);  // 输出: 4, 6

在上面的例子中,我们定义了一个抽象类?Point,它包含了抽象属性?x?和?y,以及抽象方法?move。抽象方法不包含具体的实现,而是留给子类去实现。

然后,我们创建了一个子类?MyPoint,该类继承自抽象类?Point。在子类中,我们必须实现抽象类中所有的抽象属性和方法。

最后,我们创建了一个?MyPoint?类的实例?point,并进行了一次坐标的移动。输出结果与之前的示例相同。

抽象类和接口的区别

抽象类和接口是 TypeScript 中用于定义和约束类和对象行为的关键概念,它们有以下几点区别:

1. 实例化: 接口不能被实例化,而抽象类也不能直接被实例化,只能作为其他类的基类。

2. 实现限制: 类可以实现多个接口,但只能继承一个抽象类。

3. 成员实现: 接口中的成员都是抽象的,没有具体的实现细节,而抽象类可以包含具体的成员实现。

4. 属性和方法: 接口可以包含属性、方法、索引签名和构造签名等成员,而抽象类可以包含属性、方法(包括抽象方法和具体方法)、构造函数和访问修饰符等成员。

5. 多态性: 抽象类可以实现多态,通过在基类中定义抽象方法来强制子类必须实现该方法。而接口无法实现多态,只能用于描述对象的结构。

6. 继承关系: 抽象类可以继承其他类或抽象类,也可以实现接口。而接口只能继承其他接口,不能直接继承类。

7. 用途: 抽象类适用于定义一些相似的子类,通过继承抽象类来避免重复代码并实现代码复用。接口常用于描述对象的结构,用于类型检查和约束。

抽象类主要用于定义类的共性和结构,可以包含具体的实现细节;而接口主要用于描述对象的结构,强调规范和约束,不包含具体的实现细节。

抽象类更适合用于具有相似行为的类的继承和扩展,而接口更适合用于对象的类型检查和约束。

构造函数接口

构造函数接口用于描述一个类的构造函数的类型。通过构造函数接口,我们可以定义类的构造函数参数的类型和返回的实例类型。

interface Point {
  x: number;
  y: number;
}

interface PointConstructor {
  new (x: number, y: number): Point;
}

class MyPoint implements Point {
  x: number;
  y: number;
  
  constructor(x: number, y: number) {
    this.x = x;
    this.y = y;
  }
}

const PointClass: PointConstructor = MyPoint;
const point: Point = new PointClass(1, 2);
console.log(point.x, point.y);  // 输出: 1, 2

接口的继承

接口之间可以通过继承来建立关系,使一个接口可以继承另一个或多个接口的成员。接口的继承可以通过关键字?extends?来实现。

接口继承接口
interface Box {
  area():number;
  length():number;
}

interface Box2 extends Box {
  volumn():number;
}

// Box3这个类需要同时实现Box和Box2中的方法
class Box3 implements Box2 {
  area() {
    return 1
  }
  length() {
    return 2
  }
  volumn() {
    return 3;
  }
}
接口继承类
class Box {
  protected uname:string = 'zs';
}

interface Box2 extends Box {
  pwd:string;
}

class Box3 extends Box implements Box2 {
  pwd:string;
  constructor(pwd:string) {
    super();
    this.pwd = pwd
  }
  showName() {
    console.log(this.uname)
    console.log(this.pwd)
  }
}

let b = new Box3('123456')
b.showName()

继承接口可以实现接口之间的层次关系,使得接口能够更好地组织和描述对象的结构和行为。同时,这也提供了代码共享和重用的机制,有助于增强代码的可读性和可维护性。

文章来源:https://blog.csdn.net/kkkys_kkk/article/details/135297401
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。