[返回编程技术首页]·[所有跟帖]·[ 回复本帖 ] ·[热门原创] ·[繁體閱讀]·[坛主管理]

深入探讨TypeScript中implements与extends的区别

送交者: wecode[★★声望品衔9★★] 于 2024-01-23 20:35 已读 512 次  

wecode的个人频道

+关注
在 TypeScript 中,我们经常会遇到两个关键字,即 implements 和 extends。虽然它们在代码中看起来相似,但它们实际上有着不同的作用和用法。本文将深入探讨这两个关键字之间的区别,帮助读者更好地理解它们在 TypeScript 中的应用。class和interface的区别

要理解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中类时有抽象类和非抽象类之分的,是面向对象编程中两种不同的类的概念,主要区别在于类的设计和用途。

抽象类

抽象类是一种不能被实例化的类,用于定义对象的通用结构和行为。抽象类可以包含抽象方法(没有具体实现的方法)和具体方法(有实际实现的方法)。

特点:

抽象类不能被直接实例化,即不能使用 new 关键字创建抽象类的实例。抽象类主要用于作为其他类的基类,提供通用的属性和方法的框架,但不能独立存在。

抽象类中可以包含抽象方法,这些方法没有具体的实现,而是要求子类必须提供具体的实现。抽象方法使用 abstract 关键字标记。

抽象类可以被其他类继承,子类必须实现抽象类中的所有抽象方法,否则子类也必须声明为抽象类。

复制

abstract class Shape {

abstract draw(): void; // 抽象方法

area() {

console.log("Calculating area...");

}

}

class Circle extends Shape {

draw() {

console.log("Drawing a circle");

}

}

非抽象类

非抽象类是可以被实例化的类,它可以包含属性、方法,以及具体的实现。非抽象类通常用于创建可以直接实例化和使用的对象。

特点:

可以被实例化:非抽象类可以被直接实例化,使用 new 关键字可以创建非抽象类的对象。

具体方法:非抽象类中可以包含具体的方法实现,而不仅限于抽象方法。这些方法可以被继承或直接调用。

继承:非抽象类可以被其他类继承,子类可以选择性地覆盖或扩展父类中的方法。

复制

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 关键字主要用于创建类或接口的继承关系。通过 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,

};

小结

非抽象类继承非抽象类:

简单的属性和方法的继承。

子类继承父类的属性和方法,可以选择性地覆盖或扩展父类的方法。

非抽象类继承抽象类:

子类需要实现抽象类中定义的抽象方法。

对于属性,非抽象类可以直接继承,无需单独定义。

抽象类继承非抽象类:

简单的属性和方法的继承。

子类继承父类的属性和方法。

抽象类继承抽象类:

子类继承父类的属性和方法。

子类必须提供抽象类中定义的抽象方法的具体实现。

类继承接口:

类无法直接使用 extends 继承接口,只能使用 implements 去实现接口。

接口继承类:

接口不能直接继承类。

类可以作为接口的一部分,实现接口继承类,强调类的实例结构。

接口继承接口:

简单的属性和方法的继承。

接口可以通过 extends 关键字继承其他接口。

implements关键字

implements 关键字来确保一个类实现了特定的接口。接口定义了一组成员(方法、属性等),而通过 implements,你可以告诉 TypeScript 编译器,这个类将提供接口中指定的所有成员。

类实现类

非抽象类实现非抽象类

实现类里面所有的属性和方法都要在目标类里重新定义和实现。

复制

// 定义一个非抽象类

class MyBaseClass {

baseMethod(): void {

console.log("Base class method");

}

}

// 定义另一个非抽象类并实现 MyBaseClass

class 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;

}

// 另一个抽象类继承自 BaseAbstractClass

abstract 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 定义为抽象方法

类实现接口

抽象类实现接口:接口所有属性都要重新定义,接口所有方法需要实现或者使用 abstract 定义为抽象方法

非抽象类实现接口:接口所有属性都要重新定义,接口所有方法需要实现

接口实现接口:接口不能实现接口

接口实现类:接口不能实现类

extends和implements的区别

通过前文的介绍,相信你已经能够清晰地区分这两者了。在本节中,我将对以上内容进行总结。首先,我们列举它们的共同点:

都可以建立类与类之间的关联。

针对抽象类中的抽象方法,都必须要进行实现。

接下来,我们详细列举它们的不同之处:

extends能够实现接口与接口、接口与类的继承;而implements不能实现接口与接口、接口与类的实现。

implements可以实现类实现接口,而extends不能实现类继承接口。

在使用implements时,必须定义或实现所有属性和方法;而extends只需重新定义或实现方法,对于属性来说,可以直接继承,无需单独定义。

总结

extends 用于建立类与类之间的继承关系,而 implements 用于确保类实现了特定的接口。 extends 在类的层次结构中用于继承,而 implements 则用于实现接口的规范。
喜欢wecode朋友的这个贴子的话, 请点这里投票,“赞”助支持!

内容来自网友分享,若违规或者侵犯您的权益,请联系我们

所有跟帖:   ( 主贴楼主有权删除不文明回复,拉黑不受欢迎的用户 )


用户名: 密码: [--注册ID--]

标 题:

粗体 斜体 下划线 居中 插入图片插入图片 插入Flash插入Flash动画


     图片上传  Youtube代码器  预览辅助



[ 留园条例 ] [ 广告服务 ] [ 联系我们 ] [ 个人帐户 ] [ 创建您的定制新论坛频道 ] [ Contact us ]