在 TypeScript 中,我们经常会遇到两个关键字,即 implements 和 extends。虽然它们在代码中看起来相似,但它们实际上有着不同的作用和用法。本文将深入探讨这两个关键字之间的区别,帮助读者更好地理解它们在 TypeScript 中的应用。
要理解extends和implements的区别,得对类和接口的概念熟稔于心,它们在语法和用途上的关键区别。
记住:
类是一种具有属性和方法的蓝图,它用于创建对象。通过类,可以实例化对象,让多个对象共享相同的结构和行为。类支持封装、继承和多态等面向对象的特性。
class Person { name: string; constructor(name: string) { this.name = name; } sayHello() { console.log(`Hello, my name is ${this.name}.`); }}const person = new Person("John");person.sayHello();
用途:
在typescript中类时有抽象类和非抽象类之分的,是面向对象编程中两种不同的类的概念,主要区别在于类的设计和用途。
抽象类是一种不能被实例化的类,用于定义对象的通用结构和行为。抽象类可以包含抽象方法(没有具体实现的方法)和具体方法(有实际实现的方法)。
特点:
abstract class Shape { abstract draw(): void; // 抽象方法 area() { console.log("Calculating area..."); }}class Circle extends Shape { draw() { console.log("Drawing a circle"); }}
非抽象类是可以被实例化的类,它可以包含属性、方法,以及具体的实现。非抽象类通常用于创建可以直接实例化和使用的对象。
特点:
class Animal { name: string; constructor(name: string) { this.name = name; } makeSound() { console.log("Some generic sound"); }}class Dog extends Animal { makeSound() { console.log("Woof! Woof!"); }}
抽象类:
非抽象类:
接口是一种用于描述对象形状(即属性和方法)的抽象结构。接口并没有提供具体的实现,而是定义了一组规范,用于确保符合该接口的对象具有特定的结构。
interface Person { name: string; sayHello(): void;}const person: Person = { name: "John", sayHello() { console.log(`Hello, my name is ${this.name}.`); }};person.sayHello();
用途:
extends 关键字主要用于创建类或接口的继承关系。通过 extends,一个类或接口可以继承另一个类或接口的属性和方法,从而可以重用已有的代码并扩展其功能。不可以重写属性,但是可以重写方法。
非抽象类继承非抽象类即简单的属性和方法的继承。
当一个非抽象类继承另一个非抽象类时,子类会继承父类的属性和方法,并且子类可以选择性地覆盖或扩展父类的方法。
// 父类class Animal { name: string; constructor(name: string) { this.name = name; } makeSound() { console.log("Some generic sound"); }}// 子类继承父类class Dog extends Animal { // 可以覆盖父类的方法 makeSound() { console.log("Woof! Woof!"); } // 可以扩展父类的方法 greetOwner() { console.log(`Hello, owner! My name is ${this.name}.`); }}
当一个非抽象类继承抽象类时,子类必须提供抽象类中定义的抽象方法的具体实现。抽象类中的抽象方法是没有具体实现的方法,而是由子类去实现。这强制了子类必须遵循抽象类中定义的一些行为规范。
// 抽象类abstract class Shape { abstract draw(): void; // 抽象方法 area() { console.log("Calculating area..."); }}// 非抽象类继承抽象类class Circle extends Shape { radius: number; constructor(radius: number) { super(); // 调用父类的构造函数 this.radius = radius; } // 实现抽象方法 draw() { console.log("Drawing a circle"); } // 可以扩展父类的方法 calculateArea() { const area = Math.PI * this.radius ** 2; console.log(`Area: ${area}`); }}
抽象类可以继承非抽象类的属性和方法,而且它也可以包含抽象方法,这些抽象方法需要在子类中进行实现。
// 非抽象类class Animal { name: string; constructor(name: string) { this.name = name; } makeSound() { console.log("Some generic sound"); }}// 抽象类继承非抽象类abstract class Dog extends Animal { abstract wagTail(): void; // 抽象方法 bark() { console.log("Woof! Woof!"); }}// 具体的子类实现抽象类中的抽象方法class Labrador extends Dog { wagTail() { console.log("Tail wagging..."); }}
抽象类是可以继承抽象类的。这种继承关系允许在类的层次结构中建立一种更高层次的抽象,并要求子类实现更具体的行为。
// 抽象类abstract class Animal { abstract makeSound(): void; // 抽象方法 move() { console.log("Animal is moving..."); }}// 另一个抽象类继承抽象类abstract class Bird extends Animal { abstract fly(): void; // 抽象方法 chirp() { console.log("Chirp chirp!"); }}// 具体的子类实现抽象类中的抽象方法class Sparrow extends Bird { makeSound() { console.log("Sparrow is making sound"); } fly() { console.log("Sparrow is flying"); }}
类是无法直接使用extends继承接口的,只能使用implements去实现接口。
接口是不能直接继承类的。
类可以作为接口的一部分,从而实现接口继承类。这意味着你可以定义一个接口,它包含了类的实例部分的成员,然后其他类可以实现这个接口。
这样的话,实际上是在强调类的实例结构。
abstract class AbstractParent { abstract abstractFunc():string} // 接口继承类interface IExample extends AbstractParent{ name:string age:number}
需要注意的是,这种方式强调的是类的实例结构,而不是类的构造函数或静态部分。因此,只有类的实例部分的成员才会被包含在接口中。
接口可以通过 extends 关键字来继承其他接口,从而形成接口继承接口的关系。
// 定义一个基础接口interface Shape { color: string;}// 定义继承自 Shape 接口的新接口interface Square extends Shape { sideLength: number;}// 使用新接口let square: Square = { color: "red", sideLength: 10,};
简单的属性和方法的继承。
子类继承父类的属性和方法,可以选择性地覆盖或扩展父类的方法。
implements 关键字来确保一个类实现了特定的接口。接口定义了一组成员(方法、属性等),而通过 implements,你可以告诉 TypeScript 编译器,这个类将提供接口中指定的所有成员。
实现类里面所有的属性和方法都要在目标类里重新定义和实现。
// 定义一个非抽象类class MyBaseClass { baseMethod(): void { console.log("Base class method"); }}// 定义另一个非抽象类并实现 MyBaseClassclass MyDerivedClass implements MyBaseClass { baseMethod(): void { console.log("Derived class method"); } derivedMethod(): void { console.log("Derived class-specific method"); }}
抽象类里的所有属性和方法都需要在非抽象类里定义和实现。
// 定义一个抽象类abstract class MyAbstractClass { abstract abstractMethod(): void;}// 定义一个非抽象类并实现抽象类class MyNonAbstractClass implements MyAbstractClass { abstractMethod(): void { console.log("Implementation of abstractMethod"); } nonAbstractMethod(): void { console.log("Non-abstract class-specific method"); }}
实现类里面所有的属性都要在目标类里重新定义,所有方法需要被实现或者使用 abstract 定义为抽象方法。
// 定义一个抽象类abstract class BaseAbstractClass { abstract abstractMethod(): void; abstract abstractProperty: string;}// 另一个抽象类继承自 BaseAbstractClassabstract class DerivedAbstractClass extends BaseAbstractClass { // 重新定义属性 abstract abstractProperty: string; concreteProperty: number = 42; // 实现抽象方法 abstractMethod(): void { console.log("Implementation of abstractMethod in DerivedAbstractClass"); } // 新的抽象方法 abstract newAbstractMethod(): void;}// 具体的实现类class ConcreteClass extends DerivedAbstractClass { // 重新定义属性 abstractProperty: string = "Concrete Property"; // 实现新的抽象方法 newAbstractMethod(): void { console.log("Implementation of newAbstractMethod in ConcreteClass"); } // 新的具体方法 concreteMethod(): void { console.log("Concrete method in ConcreteClass"); }}
非抽象类里面所有的属性都要在抽象类里重新定义,所有方法需要被实现或者使用 abstract 定义为抽象方法。
// 定义一个非抽象类class MyBaseClass { nonAbstractProperty: string = "Non-abstract Property"; nonAbstractMethod(): void { console.log("Non-abstract method in MyBaseClass"); }}// 抽象类继承自非抽象类abstract class MyAbstractClass extends MyBaseClass { // 重新定义属性 abstract nonAbstractProperty: string; // 实现非抽象方法 nonAbstractMethod(): void { console.log("Implementation of nonAbstractMethod in MyAbstractClass"); } // 新的抽象方法 abstract newAbstractMethod(): void;}// 具体的实现类class ConcreteClass extends MyAbstractClass { // 重新定义属性 nonAbstractProperty: string = "Concrete Property"; // 实现新的抽象方法 newAbstractMethod(): void { console.log("Implementation of newAbstractMethod in ConcreteClass"); } // 新的具体方法 concreteMethod(): void { console.log("Concrete method in ConcreteClass"); }}
接口所有属性都要重新定义,接口所有方法需要实现或者使用 abstract 定义为抽象方法。
// 定义一个接口interface MyInterface { interfaceProperty: string; interfaceMethod(): void;}// 抽象类实现接口abstract class MyAbstractClass implements MyInterface { // 重新定义接口中的属性 interfaceProperty: string; // 实现接口中的方法 interfaceMethod(): void { console.log("Implementation of interfaceMethod in MyAbstractClass"); } // 新的抽象方法 abstract newAbstractMethod(): void;}// 具体的实现类class ConcreteClass extends MyAbstractClass { // 重新定义属性 interfaceProperty: string = "Concrete Property"; // 实现新的抽象方法 newAbstractMethod(): void { console.log("Implementation of newAbstractMethod in ConcreteClass"); } // 新的具体方法 concreteMethod(): void { console.log("Concrete method in ConcreteClass"); }}
接口所有属性都要重新定义,接口所有方法需要实现。
// 定义一个接口interface MyInterface { interfaceProperty: string; interfaceMethod(): void;}// 非抽象类实现接口class MyClass implements MyInterface { // 重新定义接口中的属性 interfaceProperty: string = "Default Property"; // 实现接口中的方法 interfaceMethod(): void { console.log("Implementation of interfaceMethod in MyClass"); } // 新的具体方法 myClassMethod(): void { console.log("Method specific to MyClass"); }}
非抽象类实现非抽象类:实现类里面所有的属性和方法都要在目标类里重新定义和实现
非抽象类实现抽象类:抽象类里的所有属性和方法都需要在非抽象类里定义和实现
抽象类实现抽象类:实现类里面所有的属性都要在目标类里重新定义,所有方法需要被实现或者使用 abstract 定义为抽象方法
抽象类实现非抽象类:非抽象类里面所有的属性都要在抽象类里重新定义,所有方法需要被实现或者使用 abstract 定义为抽象方法
通过前文的介绍,相信你已经能够清晰地区分这两者了。在本节中,我将对以上内容进行总结。首先,我们列举它们的共同点:
接下来,我们详细列举它们的不同之处:
extends 用于建立类与类之间的继承关系,而 implements 用于确保类实现了特定的接口。 extends 在类的层次结构中用于继承,而 implements 则用于实现接口的规范。
本文链接:http://www.28at.com/showinfo-26-66961-0.html深入探讨TypeScript中implements与extends的区别
声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com
上一篇: 什么?Figma 的 Fig 文件格式居然解析出来了
下一篇: Python中最常用的十个内置函数!