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



我是一名程序员,曾用多种语言编程,包括函数语言和面向对象语言。我也编写了一些Javascript,但从未在其中使用(或必须使用)多态性

现在,作为一个业余项目,我想将一些用Java和C#编写的、大量使用polymorhpism的应用程序移植到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() } }

因此,一个经典的多态情况是:在基类上迭代。

我想实现这种行为。我知道polymorhism,但我是否忽略了其他实现这种行为的"模式",或者我应该研究Javascript中的继承可能性?

如前所述,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,因此,或者您回退到duck类型,或者您必须使用isPrototypeOf,但仅在最近的浏览器中可用:

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

Object.create在不实现ES5规范的浏览器中不可用,但您可以轻松使用polyfill(请参阅链接)。

这里的"模式"是"接口"。只要myshapes集合中的所有对象都实现了printSurface()方法,就可以了。

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

我知道这可以用原型来完成,但我不是使用它的大师。我更喜欢对象文字方法(更容易可视化,并且有一个"私有"范围)

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

正如Weston所说,如果您不需要继承,那么动态语言(如Javascript)的鸭子类型特性会为您提供多态性,因为语言本身不需要强类型基类或接口。

如果您确实想使用继承并轻松地调用超类的实现,那么这可以通过原型或对象文字来实现,如Joeseph所示。

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

另请注意。如果您想使用类以OO风格对Javascript进行编程,您可以研究Javascript的许多"类系统"。Joose就是一个例子(http://joose.it)。

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

最新更新