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

时间:2012-03-24 10:16:34

标签: javascript inheritance polymorphism

我是一名程序员,他使用多种语言进行编程,包括功能和面向OO。我也编写了一些Javascript,但从未使用(或不得不使用)多态。

现在,作为一个爱好项目,我想将一些用Java和C#编写的应用程序移植到Javascript中,这些应用程序大量使用了多态性。

但是乍一看我读了很多'这是可能的但是......'

那么它有替代品吗?

我想用伪写的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() } }

这是一个经典的多态案例:迭代基类。

我想实现这种行为。我知道它多态性,但我是否有任何其他'模式'可以实现这种行为,或者我应该在Javascript中研究继承的可能性吗?

5 个答案:

答案 0 :(得分:43)

如上所述,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
}

然后,在你的应用中:

var obj = new Circle();

if (obj instanceof Shape) {
    // do something with a shape object
}

或者,鸭子打字:

if ("printSurface" in obj)
    obj.printSurface();

// or

if (obj.printSurface)
    obj.printSurface();

// or a more specific check
if (typeof obj.printSurface === "function")
    obj.printSurface();

你冷也有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
}

请注意,在这种情况下,您不能再使用instanceof了,所以或者您回退到鸭子类型或者您必须使用isPrototypeOf,但仅在最近的浏览器中可用:

if (Shape.isPrototypeOf(obj)) {
    // do something with obj
}
浏览器中没有

Object.create不能实现ES5规范,但您可以轻松使用polyfill(请参阅链接)。

答案 1 :(得分:14)

这里的“模式”将是“界面”。只要myshapes集合中的所有对象都实现printSurface()方法,您就可以了。

由于Javascript是一种动态类型语言,因此集合中的对象根本不需要相关。

答案 2 :(得分:7)

我知道这可以用原型完成,但我不是使用它的大师。 i prefer the object literal approach(更容易想象并具有“私人”范围)

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

答案 3 :(得分:4)

正如韦斯顿所说,如果你不需要继承,那么动态语言(如Javascript)的鸭类性质会为你提供多态性,因为对于强类型的基类或接口,语言本身没有要求

如果您确实想要使用继承并执行诸如调用超类的实现之类的操作,那么可以使用Joeseph所示的原型或对象文字来实现。

另一件事是查看Coffescript,因为这会编译为Javascript,以简单的语法为您提供所有OO优点。它将为您编写所有bollerplate原型设计的东西。缺点是它增加了这个额外的编译步骤。那就像上面的例子那样编写一个简单的类层次结构,然后看看javascript弹出的结果有助于说明如何完成它。

答案 4 :(得分:4)

另一方面。如果你想使用类以OO风格编写Javascript,你可以查看Javascript的许多“类系统”。一个例子是Joose(http://joose.it)。

许多客户端框架实现了自己的类系统。这方面的一个例子是ExtJS。