在 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.www897cc.com/showinfo-26-66961-0.html深入探討TypeScript中implements與extends的區別
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com
上一篇: 什么?Figma 的 Fig 文件格式居然解析出來了
下一篇: Python中最常用的十個內置函數!