简体   繁体   English

什么是 Javascript 中的多态性?

[英]What is polymorphism in Javascript?

I have read some possible article I could found on the internet on polymorphism .我已经阅读了一些我可以在互联网上找到的关于polymorphism 的可能的文章。 But I think I could not quite grasp the meaning of it and its importance.但我想我不能完全理解它的含义和重要性。 Most of the articles don't say why it is important and how I can achieve polymorphic behavior in OOP (of course in JavaScript).大多数文章没有说明为什么它很重要以及我如何在 OOP 中实现多态行为(当然在 JavaScript 中)。

I can not provide any code example because I haven't got the idea how to implement it, so my questions are below:我无法提供任何代码示例,因为我不知道如何实现它,所以我的问题如下:

  1. What is it?它是什么?
  2. Why we need it ?为什么我们需要它?
  3. How it works?这个怎么运作?
  4. How can I achieve this polymorphic behavior in javascript?如何在 javascript 中实现这种多态行为?

I have got this example.我有这个例子。 But it is easily understandable what will be outcome of this code.但是很容易理解这段代码的结果。 It doesn't give any clear idea about polymorphism itself.它没有给出关于多态性本身的任何清晰的概念。

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

Polymorphism is one of the tenets of Object Oriented Programming (OOP).多态性是面向对象编程 (OOP) 的原则之一。 It is the practice of designing objects to share behaviors and to be able to override shared behaviors with specific ones.它是设计对象以共享行为并能够用特定的行为覆盖共享行为的实践。 Polymorphism takes advantage of inheritance in order to make this happen.多态利用继承来实现这一点。

In OOP everything is considered to be modeled as an object.在 OOP 中,一切都被认为是作为对象建模的。 This abstraction can be taken all the way down to nuts and bolts for a car, or as broad as simply a car type with a year, make, and model.这种抽象可以一直深入到汽车的具体细节,也可以简单地概括为具有年份、品牌和型号的汽车类型。

To have a polymorphic car scenario there would be the base car type, and then there would subclasses which would inherit from car and provide their own behaviors on top of the basic behaviors a car would have.要拥有多态汽车场景,将有基本汽车类型,然后会有从汽车继承的子类,并在汽车将具有的基本行为之上提供自己的行为。 For example, a subclass could be TowTruck which would still have a year make and model, but might also have some extra behaviors and properties which could be as basic as a flag for IsTowing to as complicated as the specifics of the lift.例如,一个子类可能是 TowTruck,它仍然有一个年份的品牌和型号,但也可能有一些额外的行为和属性,这些行为和属性可能像 IsTowing 的标志一样基本,也可能像电梯的细节一样复杂。

Getting back to the example of people and employees, all employees are people, but all people are not employees.回到人和员工的例子,所有的员工都是人,但所有的人都不是员工。 Which is to say that people will be the super class, and employee the sub class.也就是说,人是超类,员工是子类。 People may have ages and weights, but they do not have salaries.人们可能有年龄和体重,但他们没有薪水。 Employees are people so they will inherently have an age and weight, but also because they are employees they will have a salary.员工是人,所以他们天生就有年龄和体重,但也因为他们是员工,他们会有薪水。

So in order to facilitate this, we will first write out the super class (Person)所以为了方便,我们先写出超类(Person)

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

And we will give Person the ability to share their information我们将赋予 Person 共享其信息的能力

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

Next we wish to have a subclass of Person, Employee接下来我们希望有一个 Person、Employee 的子类

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

And we will override the behavior of getInfo by defining one which is more fitting to an Employee我们将通过定义一个更适合 Employee 的行为来覆盖 getInfo 的行为

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

These can be used similar to your original code use这些可以类似于您的原始代码使用

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

console.log(person.getInfo());
console.log(employee.getInfo());

However, there isn't much gained using inheritance here as Employee's constructor is so similar to person's, and the only function in the prototype is being overridden.然而,在这里使用继承并没有太多好处,因为 Employee 的构造函数与 person 的构造函数如此相似,并且原型中唯一的函数被覆盖了。 The power in polymorphic design is to share behaviors.多态设计的力量在于共享行为。

As explained in this other answer , polymorphism has different interpretations.正如在另一个答案中所解释的,多态性有不同的解释。

The best explanation on the subject that I've ever read is an article by Luca Cardelli , a renown type theorist.我读过的关于这个主题的最佳解释是著名类型理论家Luca Cardelli的一篇文章。 The article is named On Understanding Types, Data Abstraction, and Polymorphism .这篇文章名为On Understanding Types, Data Abstraction, and Polymorphism

What Is it?它是什么?

Cardelli defines several types of polymorphism in this article: Cardelli 在这篇文章中定义了几种类型的多态:

  • Universal普遍的
    • parametric参数
    • inclusion包容
  • Ad-hoc特设
    • oveloading超载
    • coercion强迫

Perhaps in JavaScript, it is a bit more difficult to see the effects of polymorphism because the more classical types of polymorphism are more evident in static type systems, whereas JavaScript has a dynamic type system.或许在 JavaScript 中,要看到多态的影响有点困难,因为更经典的多态类型在静态类型系统中更为明显,而 JavaScript 具有动态类型系统。

So, for instance, there is no method or function overloading or automatic type coercions at compile time in JavaScript.因此,例如,在 JavaScript 中,在编译时没有方法或函数重载或自动类型强制。 In a dynamic language, we take most of these things for granted.在动态语言中,我们认为大多数这些事情都是理所当然的。 Neither we need something like parametric polymorphism in JavaScript due to the dynamic nature of the language.由于语言的动态特性,我们也不需要 JavaScript 中的参数多态之类的东西。

Still, JavaScript has a form of type inheritance that emulates the same ideas of subtype polymorphism (classified as inclusion polymorphism by Cardelli above) in a similar way to what we typically do in other object-oriented programing languages like Java or C# (as explained in another answer I shared above).尽管如此,JavaScript 还是有一种类型继承的形式,它以类似于我们在其他面向对象的编程语言(如 Java 或 C#)中通常所做的方式模拟子类型多态性(上面被 Cardelli 归类为包含多态性)的相同思想(如在我在上面分享的另一个答案)。

Another form of polymorphism very typical in dynamic languages is called duck typing .动态语言中非常典型的另一种多态形式称为鸭子类型

It is a mistake to believe that polymorphism is only related to object-oriented programming.认为多态只与面向对象编程有关是错误的。 Other programming models (functional, procedural, logic, etc.) offer different forms of polymorphism in their type systems, probably in a way a bit unfamiliar to those only used to OOP.其他编程模型(函数式、过程式、逻辑式等)在它们的类型系统中提供了不同形式的多态性,这对于那些只使用过 OOP 的人来说可能有点陌生。

Why We Need It?为什么我们需要它?

Polymorphism foster many good attributes in software, among other things it fosters modularity and reusability and makes the type system more flexible and malleable.多态性在软件中培养了许多良好的属性,除其他外,它促进了模块化和可重用性,并使类型系统更加灵活和可塑。 Without it, it would be really difficult to reason about types.没有它,就很难对类型进行推理。 Polymorphism makes sure that one type can be substituted by other compatible ones provided that they satisfy a public interface, so this also fosters information hiding and modularity.多态确保一种类型可以被其他兼容的类型替换,前提是它们满足公共接口,因此这也促进了信息隐藏和模块化。

How Does it Work?它是如何工作的?

This is not simple to answer, different languages have different ways to implement it.这并不容易回答,不同的语言有不同的实现方式。 In the case of JavaScript, as mentioned above, you will see it materialize in the form of type hierarchies using prototypal inheritance and you can also exploit it using duck typing.在 JavaScript 的情况下,如上所述,您将看到它使用原型继承以类型层次结构的形式具体化,您也可以使用鸭子类型来利用它。

The subject is a bit broad and you opened two many questions in a single post.这个主题有点宽泛,你在一篇文章中提出了两个很多问题。 Perhaps it is best that you start by reading Cardelli's paper and then try to understand polymorphism irrespective of any language or programming paradigm, then you will start making associations between the theoretical concepts and what any particular language like JavaScript has to offer to implement those ideas.也许你最好先阅读 Cardelli 的论文,然后尝试理解多态性,而不考虑任何语言或编程范式,然后你将开始在理论概念与任何特定语言(如 JavaScript)之间建立关联,以实现这些想法。

What is the purpose of polymorphism?多态的目的是什么?

Polymorphism makes a static type system more flexible without losing (significant) static type safety by loosening the conditions for type equivalence.多态性通过放宽类型等价的条件,使静态类型系统更加灵活,而不会失去(重要的)静态类型安全性。 The proof remains that a program will only run if it doesn't contain any type errors.证据仍然是程序只有在不包含任何类型错误时才会运行。

A polymorphic function or data type is more general than a monomorphic one, because it can be used in a wider range of scenarios.多态函数或数据类型比单态函数或数据类型更通用,因为它可以用于更广泛的场景。 In this sense polymorphism represents the idea of generalization in strictly typed languages.在这个意义上,多态代表了严格类型语言中的泛化思想。

How does this apply to Javascript?这如何适用于 Javascript?

Javascript has a weak, dynamic type system. Javascript 有一个弱的动态类型系统。 Such a type system is equivalent with a strict type system containing only one type.这样的类型系统等价于只包含一种类型的严格类型系统。 We can think of such a type as a huge union type (pseudo syntax):我们可以将这样的类型视为一个巨大的联合类型(伪语法):

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

Every value will be associated to one of these type alternatives at run-time.在运行时,每个值都将与这些类型替代之一相关联。 And since Javascript is weakly typed, every value can change its type any number of times.由于 Javascript 是弱类型的,因此每个值都可以多次更改其类型。

If we take a type theoretical perspective and consider that there is only one type, we can say with certainty that Javascript's type system doesn't have a notion of polymorphism.如果我们从类型理论的角度来看,并认为只有一种类型,我们可以肯定地说 Javascript 的类型系统没有多态的概念。 Instead we have duck typing and implicit type coercion.相反,我们有鸭子类型和隐式类型强制。

But this shouldn't keep us from thinking about types in our programs.但这不应该阻止我们考虑程序中的类型。 Due to the lack of types in Javascript we need to infer them during the coding process.由于 Javascript 中缺少类型,我们需要在编码过程中推断它们。 Our mind have to stand in for the missing compiler, ie as soon as we look at a program we must recognize not only the algorithms, but also the underlying (maybe polymorphic) types.我们的头脑必须为缺少的编译器提供支持,即我们在查看程序时不仅必须识别算法,还必须识别底层(可能是多态)类型。 These types will help us to build more reliable and more robust programs.这些类型将帮助我们构建更可靠、更健壮的程序。

In order to do this properly I am going to give you an overview of the most common manifestations of polymorphism.为了正确地做到这一点,我将向您概述多态性最常见的表现形式。

Parametric polymorphism (aka generics)参数多态性(又名泛型)

Parametric polymorphism says that different types are interchangeable because types doesn't matter at all.参数多态说不同的类型是可以互换的,因为类型根本不重要。 A function that defines one or more parameters of parametric polymorphic type must not know anything about the corresponding arguments but treat them all the same, because they can adopt to any type.定义一个或多个参数多态类型参数的函数必须不了解相应参数的任何信息,但将它们全部视为相同,因为它们可以采用任何类型。 This is quite restricting, because such a function can only work with those properties of its arguments that are not part of their data:这是非常有限的,因为这样的函数只能使用不属于其数据的参数的那些属性:

// 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 polymorphism (aka overloading)临时多态性(又名重载)

Ad-hoc polymorphism says that different types are equivalent for a specific purpose only. Ad-hoc 多态性表示不同类型仅对于特定目的是等效的。 To be equivalent in this sense a type must implement a set of functions specific to that purpose.要在这个意义上等效,类型必须实现一组特定于该目的的函数。 A function that defines one or more parameters of ad-hoc polymorphic type then needs to know which sets of functions are associated to each of its arguments.定义一个或多个特定多态类型参数的函数然后需要知道哪些函数集与其每个参数相关联。

Ad-hoc polymorphism makes a function compatible to a larger domain of types. Ad-hoc 多态性使函数与更大的类型域兼容。 The following example illustrates the "map-over" purpose and how types can implement this constraint.以下示例说明了“map-over”的目的以及类型如何实现此约束。 Instead of a set of function the "mappable" constraint only includes a single map function: “可映射”约束仅包含一个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 {} );

Subtype polymorphism亚型多态性

Since other answers already cover subtype polymorphism I skip it.由于其他答案已经涵盖了子类型多态性,我跳过它。

Structural polymorphism (aka strutrual subtyping)结构多态性(又名结构子类型)

Structural polymorphism says that different types are equivalent, if they contain the same structure in such a way, that one type has all the properties of the other one but may include additional properties.结构多态性表示不同类型是等效的,如果它们以某种方式包含相同的结构,则一种类型具有另一种类型的所有属性,但可能包含其他属性。 That being said, structural polymorphism is duck typing at compile time and certainly offers some additional type safety.话虽如此,结构多态性在编译时是鸭子类型,当然提供了一些额外的类型安全。 But by claiming that two values are of the same type just because they share some properties, it completely ignores the semantic level of values:但是仅仅因为它们共享某些属性就声称两个值属于同一类型,它完全忽略了值的语义级别:

const weight = {value: 90, foo: true};
const speed =  {value: 90, foo: false, bar: [1, 2, 3]};

Unfortunately, speed is considered a subtype of weight and as soon as we compare the value properties we are virtually comparing apples with oranges.不幸的是, speed被认为是weight一个子类型,一旦我们比较value属性,我们实际上就是在比较苹果和橙子。

what is it?它是什么?

Poly= many, morphism=form or behavior shifting.多 = 多,态射 = 形式或行为转移。

why we need it ?为什么我们需要它?

In programming, It is used when we want a function's (let say function X's) interface to be flexible enough to accept different types or number of parameters.在编程中,当我们希望函数(假设函数 X 的)接口足够灵活以接受不同类型或数量的参数时,会使用它。 Also, based on changing parameters types or numbers, we might want the function X to behave differently (morphism).此外,基于改变参数类型或数字,我们可能希望函数 X 表现不同(态射)。

How it works?这个怎么运作?

We write multiple implementations of X function where each implementation accepts different parameters types or number of parameters.我们编写了 X 函数的多个实现,其中每个实现都接受不同的参数类型或参数数量。 Based on the type or number of parameter, the compiler (at runtime) decides which implementation of X should be executed when X is called from some code.根据参数的类型或数量,编译器(在运行时)决定当从某些代码调用 X 时应该执行 X 的哪个实现。

how can I achieve this polymorphic behavior in javascript?如何在 javascript 中实现这种多态行为?

JS is not a typed language so it really not meant to use OOP concepts like polymorphism. JS 不是一种类型化语言,所以它真的不打算使用像多态这样的 OOP 概念。 However, the newer version of JS now include classes and there is possibility that polymosphism could start making sense in JS, too.但是,较新版本的 JS 现在包含类,并且多态性也有可能在 JS 中开始变得有意义。 Other answers provide some interesting workarounds.其他答案提供了一些有趣的解决方法。

Polymorphism means Ability to call the same method on different objects and each object responds in different way is called POLYMORPHISM .多态意味着能够在不同的对象上调用相同的方法并且每个对象以不同的方式响应称为POLYMORPHISM

 function Animal(sound){ this.sound=sound; this.speak=function(){ return this.sound; } } //one method function showInfo(obj){ console.log(obj.speak()); } //different objects var dog = new Animal("woof"); var cat = new Animal("meow"); var cow = new Animal("humbow"); //responds different ways showInfo(dog); showInfo(cat); showInfo(cow);

JavaScript is an interpreted language, not a compiled language. JavaScript 是一种解释型语言,而不是一种编译型语言。

Compile time Polymorhism( or Static polymorphism) Compile time polymorphism is nothing but the method overloading in java,c++编译时多态(或静态多态)编译时多态不过是java,c++中的方法重载

So method overloading is not possible in javascript.所以在javascript中方法重载是不可能的。

But Dynamic (run time) polymorphism is the polymorphism existed at run-time so method overriding is possible in javascript但是动态(运行时)多态性是运行时存在的多态性,因此在 javascript 中方法覆盖是可能的

another example is PHP.另一个例子是 PHP。

Polymorphism is the ability to define a generic type of behaviour that will behave differently when applied to different types.多态性是定义通用行为类型的能力,该行为在应用于不同类型时表现不同。

Let's say we have an Animal class that implements the talk method.假设我们有一个实现talk 方法的Animal 类。 If class Dog and Cat inherit talk() from class Animal, object dog and object cat both will talk but in a different form.如果类 Dog 和 Cat 从类 Animal 继承 talk(),则对象 dog 和对象 cat 都会说话,但形式不同。

When we iterate over a collection, that collection has to support the iterable protocol.当我们迭代一个集合时,该集合必须支持可迭代协议。 It does not matter the form of the collection object whether it is an array or dictionary.集合对象的形式是数组还是字典都没有关系。

+,-,*,/ operators are polymorphic. +,-,*,/ 运算符是多态的。 Because they work with different types: complex numbers, decimal, integer.因为它们适用于不同的类型:复数、十进制、整数。

The main benefit of polymorphism is resuing the code.多态的主要好处是恢复代码。 If you have duplicate code, you need extra space in memory which decreases the performance and also you need someone or something to maintain that duplicate code.如果您有重复的代码,您需要额外的内存空间,这会降低性能,并且您还需要某人或某物来维护该重复代码。

Since you reusing the single code, it helps debug your code easily由于您重用单个代码,它有助于轻松调试您的代码

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM