我应该在 javascript 中使用多态吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9850892/
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
Should I use polymorphism in javascript?
提问by Peter
I am a programmer who has programmed in several languages, both functional and OO oriented. I programmed some Javascript too, but never used (or had to use) polymorphism in it.
我是一名使用多种语言编程的程序员,包括面向功能和面向对象的语言。我也编写了一些 Javascript,但从未在其中使用(或不得不使用)多态性。
Now, as kind of a hobby project, I would like to port some apps that were written in Java and C# that heavily use polymorhpism to Javascript.
现在,作为一个爱好项目,我想将一些用 Java 和 C# 编写的大量使用多态性的应用程序移植到 Javascript。
But at a first glance I read lots of 'It's possible but ...'
但乍一看,我读了很多“这是可能的,但是......”
So is there an alternative to it?
那么有没有替代方案呢?
An example of what I would like to write in JS in pseudolang :
我想在pseudolang中用JS写的一个例子:
abstract class Shape{ { printSurface() } ; }
class Rect : Shape() { printSurface() { print (sideA*sideB}}
class Circle : Shape() { printSurface() { print { pi*r*r }}
TheApp { myshapes.iterate(shape s) {s.printSurface() } }
So a classic polymorphic case : iterating over baseclass.
所以一个经典的多态案例:迭代基类。
I would like to achieve this kind of behaviour. I know it ispolymorhism, but are there any other 'patterns' that I am overlooking that achieve this kind of behaviour or should I study the inheritance possibilities in Javascript?
我想实现这种行为。我知道这是多态性,但是我是否忽略了其他任何实现这种行为的“模式”,或者我应该研究 Javascript 中的继承可能性吗?
回答by ZER0
As said, JavaScript is a dynamic typed language based on prototypal inheritance, so you can't really use the same approach of typed languages. A JS version of what you wrote, could be:
如前所述,JavaScript 是一种基于原型继承的动态类型语言,因此您不能真正使用与类型语言相同的方法。您所写内容的 JS 版本可能是:
function Shape(){
throw new Error("Abstract class")
}
Shape.prototype.printSurface = function () {
throw new Error ("Not implemented");
}
function Rect() {
// constructor;
}
Rect.prototype = Object.create(Shape.prototype);
Rect.prototype.printSurface = function() {
// Rect implementation
}
function Circle() {
// constructor;
}
Circle.prototype = Object.create(Shape.prototype);
Circle.prototype.printSurface = function() {
// Circle implementation
}
Then, in your app:
然后,在您的应用中:
var obj = new Circle();
if (obj instanceof Shape) {
// do something with a shape object
}
Or, with duck typing:
或者,使用鸭子输入:
if ("printSurface" in obj)
obj.printSurface();
// or
if (obj.printSurface)
obj.printSurface();
// or a more specific check
if (typeof obj.printSurface === "function")
obj.printSurface();
You cold also have Shape
as object without any constructor, that it's more "abstract class" like:
你也有Shape
作为没有任何构造函数的对象,它更像是“抽象类”,例如:
var Shape = {
printSurface : function () {
throw new Error ("Not implemented");
}
}
function Rect() {
// constructor;
}
Rect.prototype = Object.create(Shape);
Rect.prototype.printSurface = function() {
// Rect implementation
}
function Circle() {
// constructor;
}
Circle.prototype = Object.create(Shape);
Circle.prototype.printSurface = function() {
// Circle implementation
}
Notice that in this case, you can't use instanceof
anymore, so or you fallback to duck typing or you have to use isPrototypeOf
, but is available only in recent browsers:
请注意,在这种情况下,您不能再使用instanceof
,因此或者您退回到鸭子输入或者您必须使用isPrototypeOf
,但仅在最近的浏览器中可用:
if (Shape.isPrototypeOf(obj)) {
// do something with obj
}
Object.createis not available in browser that doesn't implement ES5 specs, but you can easily use a polyfill (see the link).
Object.create在未实现 ES5 规范的浏览器中不可用,但您可以轻松使用 polyfill(请参阅链接)。
回答by Weston
The "pattern" in play here would be "interface". As long as all the objects in the myshapes
collection implement the printSurface()
method, you will be fine.
这里的“模式”是“界面”。只要集合中的所有对象都myshapes
实现了该printSurface()
方法,就可以了。
Since Javascript is a dynamically typed language, the objects in a collection don't need to be related at all.
由于 Javascript 是一种动态类型语言,因此集合中的对象根本不需要相关。
回答by Joseph
i know this can be done with prototypesbut i am not a master of using it. i prefer the object literal approach(easier to visualize and has a "private" scope)
我知道这可以用原型来完成,但我不是使用它的高手。我更喜欢对象字面量方法(更容易可视化并且具有“私有”范围)
//shape class
var shape = function() {
//return an object which "shape" represents
return {
printSurface: function() {
alert('blank');
},
toInherit: function() {
alert('inherited from shape');
}
}
};
//rect class
var rect = function() {
//inherit shape
var rectObj = shape();
//private variable
var imPrivate = 'Arrr, i have been found by getter!';
//override shape's function
rectObj.printSurface = function(msg) {
alert('surface of rect is ' + msg);
}
//you can add functions too
rectObj.newfunction = function() {
alert('i was added in rect');
}
//getters and setters for private stuff work too
rectObj.newGetter = function(){
return imPrivate;
}
//return the object which represents your rectangle
return rectObj;
}
//new rectangle
var myrect = rect();
//this is the overridden function
myrect.printSurface('foo');
//the appended function
myrect.newfunction();
//inherited function
myrect.toInherit();
//testing the getter
alert(myrect.newGetter());
?
?
回答by Johnno Loggie
As Weston says, if you don't have the need for inheritance then the duck-typed nature of a dynamic language such as Javascript gives you polymorphism since there is no requirement in the language itself for a strongly typed base class or interface.
正如韦斯顿所说,如果您不需要继承,那么诸如 Javascript 之类的动态语言的鸭子类型特性会为您提供多态性,因为语言本身不需要强类型基类或接口。
If you do want to use inheritance and do things like calling a superclass's implementation easily then this can be achieved with prototypes or object literals as shown by Joeseph.
如果您确实想使用继承并轻松地调用超类的实现,那么这可以通过原型或对象文字来实现,如 Joeseph 所示。
Another thing would be to look at Coffescriptsince this compiles down to Javascript giving you all the OO goodness in a simple syntax. It will write all of the bollerplate prototyping stuff for you. The disadvantage is that it adds this extra compilation step. That said writing a simple class hierarchy like your example above and then seeing what javascript pops out as a result helps show how it can all be done.
另一件事是查看Coffescript,因为它可以编译为 Javascript,以简单的语法为您提供所有面向对象的优点。它将为您编写所有的样板原型。缺点是它增加了这个额外的编译步骤。也就是说,像上面的示例一样编写一个简单的类层次结构,然后查看 javascript 弹出的结果有助于展示如何完成所有操作。
回答by Weston
On another note. If you want to program Javascript in an OO style using classes, you could look into the many "class-systems" for Javascript. One example is Joose (http://joose.it).
另一个注意事项。如果您想使用类以面向对象的方式编写 Javascript,您可以查看 Javascript 的许多“类系统”。一个例子是 Joose (http://joose.it)。
Many client side frameworks implement their own class system. An example of this is ExtJS.
许多客户端框架实现了它们自己的类系统。这方面的一个例子是 ExtJS。