简体   繁体   English

我应该在javascript中使用多态吗?

[英]Should I use polymorphism in javascript?

I am a programmer who has programmed in several languages, both functional and OO oriented. 我是一名程序员,他使用多种语言进行编程,包括功能和面向OO。 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 : 我想用伪写的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 is polymorhism, 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中研究继承的可能性?

As said, JavaScript is a dynamic typed language based on prototypal inheritance, so you can't really use the same approach of typed languages. 如上所述,JavaScript是一种基于原型继承的动态类型语言,因此您无法真正使用相同的类型语言方法。 A JS version of what you wrote, could be: 您编写的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 duck typing或者您必须使用isPrototypeOf ,但仅在最近的浏览器中可用:

if (Shape.isPrototypeOf(obj)) {
    // do something with obj
}

Object.create is not available in browser that doesn't implement ES5 specs, but you can easily use a polyfill (see the link). 在没有实现ES5规范的浏览器中没有Object.create ,但您可以轻松使用polyfill(请参阅链接)。

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是动态类型语言,因此集合中的对象根本不需要相关。

i know this can be done with prototypes but 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());

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. 正如Weston所说,如果你不需要继承,那么像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 Coffescript since this compiles down to Javascript giving you all the OO goodness in a simple syntax. 另一件事是看Coffescript,因为它编译为Javascript,以简单的语法为您提供所有OO优点。 It will write all of the bollerplate prototyping stuff for you. 它将为您编写所有bollerplate原型设计的东西。 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. 这就是说像上面的例子那样编写一个简单的类层次结构,然后看看javascript弹出的结果有助于展示它是如何完成的。

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. 如果你想使用类以OO风格编写Javascript,你可以查看Javascript的许多“类系统”。 One example is Joose (http://joose.it). 一个例子是Joose(http://joose.it)。

Many client side frameworks implement their own class system. 许多客户端框架实现了自己的类系统。 An example of this is ExtJS. 这方面的一个例子是ExtJS。

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

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