什么是Javascript中的多态性?

我已经阅读了一些我可以在互联网上find的关于多态性的文章 。 但是我觉得我不太明白它的意思和它的重要性。 大多数文章没有说明为什么它是重要的,我怎么能在OOP中实现多态行为(当然在JavaScript中)。

我不能提供任何代码示例,因为我还没有想法如何实现它,所以我的问题如下:

  1. 它是什么?
  2. 为什么我们需要它?
  3. 怎么运行的?
  4. 我怎么能在JavaScript中实现这种多态行为?

我有这个例子。 但是这个代码的结果是容易理解的。 它没有给出关于多态性本身的清晰的概念。

function Person(age, weight) { this.age = age; this.weight = weight; this.getInfo = function() { return "I am " + this.age + " years old " + "and weighs " + this.weight +" kilo."; } } function Employee(age, weight, salary) { this.salary = salary; this.age = age; this.weight = weight; this.getInfo = function() { return "I am " + this.age + " years old " + "and weighs " + this.weight +" kilo " + "and earns " + this.salary + " dollar."; } } Employee.prototype = new Person(); Employee.prototype.constructor = Employee; // The argument, 'obj', can be of any kind // which method, getInfo(), to be executed depend on the object // that 'obj' refer to. function showInfo(obj) { document.write(obj.getInfo() + "<br>"); } var person = new Person(50,90); var employee = new Employee(43,80,50000); showInfo(person); showInfo(employee); 

多态是面向对象编程(OOP)的原则之一。 这是devise对象共享行为,并能够用特定行为覆盖共享行为的做法。 多态性利用inheritance来实现这一点。

在OOP中,所有东西都被认为是一个对象。 这种抽象可以一直贯穿到汽车的螺母和螺栓上,或者像一辆一年级,一个车型和一个车型一样简单。

为了有一个多态的汽车情景将有基本的汽车types,然后将从汽车inheritance的子类,并提供自己的行为,汽车将具有的基本行为之上。 例如,一个子类可能是TowTruck,它仍然会有一年的制作和模型,但是也可能有一些额外的行为和属性,可能与IsTowing的标志一样基本,像电梯的细节一样复杂。

回到人和员工的榜样,所有的员工都是人,但所有的人都不是员工。 也就是说人会成为超级class,雇员是子class。 人们可能有年龄和重量,但他们没有工资。 员工是人,所以他们本来就有年龄和体重,还因为他们是有薪的员工。

所以为了方便这个,我们先写出超类(Person)

 function Person(age,weight){ this.age = age; this.weight = weight; } 

我们将给予人分享他们的信息的能力

 Person.prototype.getInfo = function(){ return "I am " + this.age + " years old " + "and weighs " + this.weight +" kilo."; }; 

接下来我们希望有一个Person,Employee的子类

 function Employee(age,weight,salary){ this.age = age; this.weight = weight; this.salary = salary; } Employee.prototype = new Person(); 

我们将通过定义一个更适合Employee的方法来覆盖getInfo的行为

 Employee.prototype.getInfo = function(){ return "I am " + this.age + " years old " + "and weighs " + this.weight +" kilo " + "and earns " + this.salary + " dollar."; }; 

这些可以使用类似于您原来的代码使用

 var person = new Person(50,90); var employee = new Employee(43,80,50000); console.log(person.getInfo()); console.log(employee.getInfo()); 

然而,在这里使用inheritance没有太多的收获,因为Employee的构造函数与人类非常相似,原型中唯一的函数被覆盖。 多态devise的力量是分享行为。

正如在其他答案中所解释的, 多态性有不同的解释。

关于我读过的主题的最好解释是着名的理论家卢卡·卡德利 ( Luca Cardelli )的一篇文章。 这篇文章被命名为理解types,数据抽象和多态性 。

它是什么?

Cardelli在本文中定义了几种types的多态:

  • 普遍
    • 参数
    • 包容
  • 特别指定
    • oveloading
    • 强迫

也许在JavaScript中看到多态性的效果有点难,因为更经典的多态性types在静态types系统中更为明显,而JavaScript具有dynamictypes系统。

因此,例如,在JavaScript中编译时没有方法或函数重载或自动types强制。 在dynamic语言中,我们把这些东西看作是理所当然的。 由于语言的dynamic性,我们不需要像JavaScript中的参数多态。

尽pipe如此,JavaScript有一种typesinheritance的forms,它类似于我们通常在Java或C#等其他面向对象的编程语言中所做的类似方式,模拟了亚型多态的相同概念(被Cardelli归类为包含多态)另一个答案。

dynamic语言中非常典型的多态的另一种forms称为鸭子打字 。

相信多态只与面向对象编程相关是错误的。 其他的编程模型(函数,过程,逻辑等)在它们的types系统中提供了不同forms的多态,对于那些只用于OOP的编程模型可能有点不熟悉。

为什么我们需要它?

多态性在软件中培养了许多优秀的特性,除此之外,它还促进了模块化和可重用性,使得types系统更加灵活和可塑。 没有它,就很难推理types。 多态性确保一种types可以被其他兼容的types替代,只要它们满足公共接口,这也促进了信息隐藏和模块化。

它是如何工作的?

这不是简单的回答,不同的语言有不同的实现方式。 就JavaScript而言,如上所述,您将看到它使用原型inheritance以types层次结构的forms实现,您也可以使用鸭子打字来利用它。

这个主题有点宽泛,你在一个post中打开了两个问题。 也许最好是从阅读Cardelli的论文开始,然后尝试理解多态性而不考虑任何语言或编程范式,那么您将开始在理论概念和JavaScript之类的特定语言为实现这些想法所提供的内容之间build立联系。

它是什么?

保利=多,态射=forms或行为转移。

为什么我们需要它?

在编程中,当我们想要一个函数(比如说函数X)的接口足够灵活以接受不同types或数量的参数时,就可以使用它。 此外,基于改变参数types或数字,我们可能希望函数X行为不同(态射)。

怎么运行的?

我们编写X函数的多个实现,其中每个实现接受不同的参数types或参数个数。 根据参数的types或编号,编译器(在运行时)决定从某些代码调用X时应执行哪个X的实现。

我怎么能在javascript中实现这种多态行为?

JS不是一个types化的语言,所以它并不意味着使用OOP概念,如多态。 然而,JS的新版本现在包含了类,并且多聚磷酸也有可能在JS中开始有意义。 其他答案提供了一些有趣的解决方法。

多态的目的是什么?

多态性使得静态types系统更加灵活,而不会因为放宽types等价的条件而丧失(显着的)静态types的安全性。 certificate仍然是一个程序将只运行,如果它不包含任何types的错误。

多态函数或数据types比单形函数或数据types更普遍,因为它可以在更广泛的场景中使用。 从这个意义上说,多态性代表了严格types语言中泛化的思想。

这如何适用于Javascript?

JavaScript有一个弱,dynamictypes的系统。 这种types系统与仅包含一种types的严格types系统相当。 我们可以把这种types看作一个巨大的联合types(伪语法):

 type T = | Undefined | Null | Number | String | Boolean | Symbol | Object | Array | Map | ... 

在运行时,每个值都将与这些types的替代品中的一个相关联。 而且由于Javascript是弱types的,每个值可以改变其types的任何次数。

如果我们从types理论的angular度来看,认为只有一种types,我们可以肯定地说,Javascript的types系统没有多态的概念。 相反,我们有鸭子打字和隐式强制。

但是,这不应该让我们不去考虑我们程序中的types。 由于JavaScript中缺lesstypes,我们需要在编码过程中推断它们。 我们的头脑必须代表缺失的编译器,也就是说,只要我们看一个程序,我们就不仅要识别algorithm,还要识别潜在的(也许是多态的)types。 这些types将帮助我们构build更可靠和更强大的程序。

为了做到这一点,我将给你一个多态的最常见的performance概述。

参数多态性(又名generics)

参数多态说,不同types是可以互换的,因为types根本就不重要。 定义参数多态types的一个或多个参数的函数不能知道任何关于相应参数的内容,而是将它们全部相同,因为它们可以采用任何types。 这是非常有限制的,因为这样的函数只能使用那些不是数据一部分的参数的属性:

 // parametric polymorphic functions const id = x => x; id(1); // 1 id("foo"); // "foo" const k = x => y => x; const k_ = x => y => y; k(1) ("foo"); // 1 k_(1) ("foo"); // "foo" const append = x => xs => xs.concat([x]); append(3) ([1, 2]); // [1, 2, 3] append("c") (["a", "b"]); // ["a", "b", "c"] 

即席多态(又称重载)

Ad-hoc多态性表示不同types仅用于特定用途。 为了在这个意义上相当于一个types必须实现一组特定于此目的的function。 定义ad-hoc多态types的一个或多个参数的函数然后需要知道哪些函数集与每个参数相关联。

即席多态使得函数与更大的types域兼容。 以下示例说明了“映射”目的以及types如何实现此约束。 “可映射”约束不包含一组函数,只包含一个map函数:

 // Option type class Option { cata(pattern, option) { return pattern[option.constructor.name](option.x); } map(f, opt) { return this.cata({Some: x => new Some(f(x)), None: () => this}, opt); } }; class Some extends Option { constructor(x) { super(x); this.x = x; } }; class None extends Option { constructor() { super(); } }; // ad-hoc polymorphic function const map = f => t => t.map(f, t); // helper/data const sqr = x => x * x; const xs = [1, 2, 3]; const x = new Some(5); const y = new None(); // application console.log( map(sqr) (xs) // [1, 4, 9] ); console.log( map(sqr) (x) // Some {x: 25} ); console.log( map(sqr) (y) // None {} ); 

JavaScript是一种解释型语言,而不是一种编译语言。

编译时间多态(或静态多态)编译时间多态只是在java,c ++中重载的方法

所以方法重载是不可能在JavaScript中。

但dynamic(运行时)多态是运行时存在的多态,所以在JavaScript中可以覆盖方法

另一个例子是PHP。