2012-03-24 10 views
32

私はいくつかの言語でプログラミングされたプログラマーです。機能性とOO指向の両方です。私もJavascriptをプログラミングしましたが、ポリモーフィズムを使ったことはありませんでした。JavaScriptで多型を使用すべきですか?

今、ホビープロジェクトの一種として、JavaとC#で書かれたいくつかのアプリを移植したいと思います.JavaScriptにポリモーピズムを多用しています。

しかし、一目見ただけで私は

「それが可能だけど...」をたくさん読んだからの代替はありますか?

私は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() } } 

だから、古典的な多型の場合:基本クラスを反復処理。

この種の動作を達成したいと思います。私はそれを知っていますポリモルフィズムですが、この種の動作を達成するために見落としている他のパターンがありますか、またはJavascriptで継承可能性を調べるべきですか?

答えて

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 
} 
01この場合には、あなたはもう instanceofを使用することはできませんので、またはあなたがダックタイピングにフォールバックするか、 isPrototypeOfを使用する必要がありますが、唯一、最近のブラウザで利用可能であることを

お知らせ:

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

Object.createはでは使用できませんブラウザではES5仕様を実装していませんが、簡単にpolyfillを使用できます(リンクを参照)。

+0

Tx、非常に良い答え。しかし、実際には、クラスフレームワークのJOOSEに行きます。 – Peter

+0

これはドキュメントでは機能しません。 Documentから継承したNMLDocumentを作成したかったのですが、奇妙な '[LenientThis]'エラーが出ました。 – m93a

14

ここで遊ぶ "パターン"は "インターフェース"です。 myshapesコレクション内のすべてのオブジェクトがprintSurface()メソッドを実装している限り、問題ありません。

Javascriptは動的に型指定された言語なので、コレクション内のオブジェクトはまったく関連する必要はありません。

+1

はい、ベル、パイソンのような鐘を鳴らしますか? – Peter

+1

私が使用した同じ例もここに表示されます: http://knol.google.com/k/programming-to-the-interface-in-javascript-yes-it-can-be-done-er-i-平均偽造# – Peter

+1

私はこの答えがより多くupvotedされていない理由を得ることはありません。 JavaScriptに関する単純な真実を指摘しています。多形性はプロパティの名前を同じにするだけです。気にする型の制約はありません。 – hayavuk

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

+0

私はそれを後で見る必要がありますが、コードサンプルを提供しようとする人は誰ですか? – Peter

+1

@Weston:別の答えになるほど十分なテーマではありませんか?フレームワークはそこで議論することができます。現時点では、パフォーマンスペナルティは常に許容可能ですか? – Peter

4

(視覚化し、「プライベート」スコープを持っているしやすいです) Javascriptは多型性を提供するので、厳密に型指定された基本クラスまたはインタフェースのための言語自体には要件がないためです。

継承を使い、スーパークラスの実装を簡単に呼び出すようなことをしたい場合は、Joesephのようにプロトタイプやオブジェクトリテラルで簡単に実現できます。

Coffescriptは、これがJavascriptにコンパイルされているため、単純な構文ですべてのオブジェクト指向の良さを示すため、別のことがあります。それはあなたのためのbolplplateプロトタイプのものをすべて書きます。欠点は、この追加のコンパイルステップを追加することです。あなたの上の例のような単純なクラス階層を作成し、その結果としてjavascriptがポップアウトするのを見て、どのようにしてすべてのことができるかを示します。

+0

Coffeescript私は知っていますが、コンパイルのステップは私にはあまりにも多くのものです。 – Peter

4

もう1つ注意してください。クラスを使用してOOスタイルでJavascriptをプログラミングしたい場合は、Javascriptのための多くの「クラスシステム」を調べることができます。 1つの例はJoose(http://joose.it)です。

多くのクライアントサイドフレームワークは、独自のクラスシステムを実装しています。これの一例はExtJSです。

+2

これを試してみると、それは本当にとても素敵です – Peter

+0

またはクラスについて忘れて、オブジェクトを受け入れてください。 – hayavuk

関連する問題