什么是 Javascript 中的多态性?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27642239/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is polymorphism in Javascript?
提问by AL-zami
I have read some possible article I could found on the internet on 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).
我已经阅读了一些我可以在互联网上找到的关于polymorphism 的可能的文章。但我想我不能完全理解它的含义和重要性。大多数文章没有说明为什么它很重要以及我如何在 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:
我无法提供任何代码示例,因为我不知道如何实现它,所以我的问题如下:
- What is it?
- Why we need it ?
- How it works?
- 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);
回答by Travis J
Polymorphism is one of the tenets of Object Oriented Programming (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.
多态性是面向对象编程 (OOP) 的原则之一。它是设计对象以共享行为并能够用特定的行为覆盖共享行为的实践。多态利用继承来实现这一点。
In OOP everything is considered to be modeled as an object. 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.
在 OOP 中,一切都被视为被建模为对象。这种抽象可以一直深入到汽车的具体细节,也可以简单地概括为具有年份、品牌和型号的汽车类型。
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. The power in polymorphic design is to share behaviors.
然而,在这里使用继承并没有太多好处,因为 Employee 的构造函数与 person 的构造函数如此相似,并且原型中唯一的函数被覆盖了。多态设计的力量在于共享行为。
回答by Edwin Dalorzo
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. The article is named On Understanding Types, Data Abstraction, and Polymorphism.
我读过的关于这个主题的最佳解释是著名类型理论家Luca Cardelli的一篇文章。这篇文章的名字是关于理解类型、数据抽象和多态。
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. 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 中,在编译时没有方法或函数重载或自动类型强制。在动态语言中,我们认为大多数这些事情都是理所当然的。由于语言的动态特性,我们也不需要 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#)中所做的方式(如在我在上面分享的另一个答案)。
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 inheritanceand 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)之间建立关联,以实现这些想法。
回答by Edwin Dalorzo
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. 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):
Javascript 有一个弱的动态类型系统。这样的类型系统等价于只包含一种类型的严格类型系统。我们可以将这样的类型视为一个巨大的联合类型(伪语法):
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. Instead we have duck typing and implicit type coercion.
如果我们从类型理论的角度来看,并认为只有一种类型,我们可以肯定地说 Javascript 的类型系统没有多态的概念。相反,我们有鸭子类型和隐式类型强制。
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. Our mind have to stand in for the missing compiler, i.e. 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.
但这不应该阻止我们考虑程序中的类型。由于 Javascript 中缺少类型,我们需要在编码过程中推断它们。我们的头脑必须为缺少的编译器提供支持,即我们在查看程序时不仅必须识别算法,还必须识别底层(可能是多态)类型。这些类型将帮助我们构建更可靠、更健壮的程序。
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. 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 多态性表示不同类型仅对于特定目的是等效的。要在这个意义上等效,类型必须实现一组特定于该目的的函数。定义一个或多个特定多态类型参数的函数然后需要知道哪些函数集与其每个参数相关联。
Ad-hoc polymorphism makes a function compatible to a larger domain of types. The following example illustrates the "map-over" purpose and how types can implement this constraint. Instead of a set of function the "mappable" constraint only includes a single mapfunction:
Ad-hoc 多态性使函数与更大的类型域兼容。以下示例说明了“map-over”的目的以及类型如何实现此约束。“可映射”约束只包含一个函数,而不是一组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, speedis considered a subtype of weightand as soon as we compare the valueproperties we are virtually comparing apples with oranges.
不幸的是,它speed被认为是一个亚型,weight一旦我们比较了它们的value特性,我们实际上就是在比较苹果和橙子。
回答by hadaytullah
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. Also, based on changing parameters types or numbers, we might want the function X to behave differently (morphism).
在编程中,当我们希望函数(假设函数 X 的)接口足够灵活以接受不同类型或数量的参数时,会使用它。此外,基于改变参数类型或数字,我们可能希望函数 X 表现不同(态射)。
How it works?
这个怎么运作?
We write multiple implementations of X function where each implementation accepts different parameters types or number of parameters. 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 时应该执行 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. However, the newer version of JS now include classes and there is possibility that polymosphism could start making sense in JS, too. Other answers provide some interesting workarounds.
JS 不是一种类型化语言,所以它真的不打算使用像多态这样的 OOP 概念。但是,较新版本的 JS 现在包含类,并且多态性也有可能在 JS 中开始变得有意义。其他答案提供了一些有趣的解决方法。
回答by SooRaj Patil
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);
回答by Apoorv
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。

