TypeScript 中的鸭子类型
什么是鸭子类型?
首先,我们要知道什么是鸭子类型。根据程序员的说法,对象的类型由其行为(如方法和属性)而不是其类决定的情况称为"鸭子类型"。
TypeScript 中的鸭子类型
TypeScript 中的接口的使用使鸭子类型成为可能。其中接口表示对象必须具有的一组方法和特征才能属于该类型。
例如,如果接口定义了函数,则任何具有名为"myFunc()"的方法的对象都可能被视为属于特定类型,而不管其类是什么。当两个对象共享相同的行为并且可以互换使用时,可以实现更大的代码灵活性。
鸭子类型强调通过考虑对象的方法和属性而不是其实际类型来评估对象是否适合某项任务。接口解释了对象必须具有的一组属性和方法,才能被视为"鸭子类型",用于特定目的。
鸭子类型的优势
鸭子类型的一个主要优势是使代码更加灵活和可重用。代码适用于具有所需方法和属性的任何对象,而不仅仅是特定类型的对象,并且可以在各种情况下使用而无需修改。鸭子类型还通过在单个代码库中启用不同种类对象的可互换使用来提高代码重用率。
鸭子类型的示例是 TypeScript
以下是如何在 TypeScript 中使用鸭子类型的示例 -
定义一个表示您希望对象具有的行为的接口。例如 -
interface Duck { quack(): void; }
创建一个实现接口的类。例如 −
class MallardDuck implements Duck { quack(): void { console.log("Quack!"); } }
创建该类的一个实例,并将其用作接口定义的类型。
let duck: Duck = new MallardDuck(); duck.quack(); // 输出:"Quack!"
创建另一个也实现该接口的类 −
class RubberDuck implements Duck { quack(): void { console.log("Squeak!"); } }
将新类实例用作接口定义的相同类型。
let duck: Duck = new RubberDuck(); duck.quack(); // 输出:"Squeak!"
如您所见,MallardDuck 和 RubberDuck 类都实现了 Duck 接口,并且 duck 变量可以分配给这两个类的实例。类型由接口中定义的行为(方法和属性)而不是类决定。
还需要注意的是,在 typescript 中,您可以使用 typeof 关键字在运行时检查对象的类型以及对象是否具有预期的方法或属性。
示例
在此示例中,Bird 和 Plane 类实现了 Flyable 接口,该接口需要 fly() 方法。这两种"鸭子类型"都可以在 goFly() 函数中互换使用。该函数并不关心传递给它的对象的实际类型,只要它具有可调用的 fly() 方法即可。
interface Flyable { fly(): void; } class Bird implements Flyable { fly(): void { console.log("Bird is flying"); } } class Plane implements Flyable { fly(): void { console.log("Plane is flying"); } } function goFly(flyable: Flyable) { flyable.fly(); } let bird = new Bird(); let plane = new Plane(); goFly(bird); // 打印"鸟正在飞行" goFly(plane); // 打印"飞机正在飞行"
编译时,它将生成以下 JavaScript 代码 −
var Bird = /** @class */ (function () { function Bird() { } Bird.prototype.fly = function () { console.log("Bird is flying"); }; return Bird; }()); var Plane = /** @class */ (function () { function Plane() { } Plane.prototype.fly = function () { console.log("Plane is flying"); }; return Plane; }()); function goFly(flyable) { flyable.fly(); } var bird = new Bird(); var plane = new Plane(); goFly(bird); // 打印"鸟正在飞行" goFly(plane); // 打印"飞机正在飞行"
输出
上述代码将产生以下输出 –
鸟正在飞行 飞机正在飞行
示例
总体而言,鸭子类型是一种强大的编程概念,它允许不同类型的对象互换使用,只要它们具有相同的方法和属性,就可以在 TypeScript 代码中实现更大的灵活性和可重用性。在此示例中,Driveable 接口、Car 和 Truck 类显示了相同的内容。
interface Driveable { drive(): void; } class Car implements Driveable { drive(): void { console.log("Car is driving"); } } class Truck implements Driveable { drive(): void { console.log("Truck is driving"); } } function goDrive(driveable: Driveable) { driveable.drive(); } let car = new Car(); let truck = new Truck(); goDrive(car); // 打印"汽车正在行驶" goDrive(truck); // 打印"卡车正在行驶"
编译时,它将生成以下 JavaScript 代码 −
var Car = /** @class */ (function () { function Car() { } Car.prototype.drive = function () { console.log("Car is driving"); }; return Car; }()); var Truck = /** @class */ (function () { function Truck() { } Truck.prototype.drive = function () { console.log("Truck is driving"); }; return Truck; }()); function goDrive(driveable) { driveable.drive(); } var car = new Car(); var truck = new Truck(); goDrive(car); // 打印"Car is driving" goDrive(truck); // 打印"Truck is driving"
输出
上述代码将产生以下输出 –
Car is driving Truck is driving
鸭子类型背后的主要思想是,代码应该编写为与具有所需方法和属性的任何对象一起工作,而不是编写为与特定对象一起工作。这可以使代码更加灵活和可重用,允许您互换使用不同类型的对象而无需更改代码。