10

OOPS base からのように、コードを再利用するための強力なツールとして常に継承を使用しています。

例として、OOPS でチェス プログラムを作成し、 is-aリレーションシップを次のように実装すると、

Class Piece{
  int teamColor;
  bool isLive;
  Positon pos;
  int Points; 
  .......
  int getTeamColor(){....}
  .......
};

Class Rook extend Piece{  //`is-a`
...... // No getTeamColor() definition here.. because the parent has the definition.
};

Class Pawn extend Piece{  //`is-a`
......// No getTeamColor() definition here.. because the parent has the definition.
};

javascript の関係でこれを行うことができますhas-aが、私が見ている欠点は、派生クラスのすべての関数も再定義する必要があることです。

例 : ルーク、ナイト、ポーン、キングなどごとに getTeamColor() を再定義します。

     var Pawn = function(teamColor,pos){
     var piece = new Piece(teamColor,pos);
     .......

     this.getTeamColor = function(){        
          return piece.getTeamColor();
    };
    }

私の質問は、javascript がデフォルト オプションとして従来の継承をサポートしていないのはなぜですか?

4

5 に答える 5

17

[2018 年の更新] JavaScript は、明らかにネイティブ言語機能の継承をサポートするようになりました。

class A { }
class B extends A { }

[/アップデート]

JavaScript はプロトタイプの方法で継承をサポートします。ここで必要なのはクラスではなく、動作のカプセル化とオーバーライド機能です。

function Piece() { }

Piece.prototype.color = "white";
Piece.prototype.getColor = function() { return this.color }
Piece.prototype.move = function() { throw "pure function" };

function Pawn() { }
Pawn.prototype = new Piece();    
Pawn.prototype.move = function() { alert("moved"); }

そしていま:

var p = new Pawn(); p.color = "black";

> p instanceof Piece

真実

 p instanceof Pawn

真実

p.getColor()

"黒"

p.move()

アラート...

これは基本的なアプローチであり、これをクラスを必要とする人にとって馴染みのあるものに変える多くのライブラリがあります。

たとえば、JayData を使用すると、以前のものをよりカプセル化された方法で記述できます (チェーンの自動コンストラクター呼び出しのボーナス付き:

var Piece = $data.Base.extend("Piece", {
  move: function()  {  throw "pure class" } 
});

var Pawn =  Piece.extend("Pawn", {
  move: function() { ... }
});

var p = new Pawn();
于 2013-04-28T08:40:40.230 に答える
7

Javascript はクラスベースのオブジェクト指向言語ではなく、プロトタイプの言語だからです。それは単なる設計上の決定です。

また、Javascript は、今日 (Node.js から ASM.js に至るまで) 私たちが Javascript を使って行うすべてのことを意味するものではありませんでした。それがまだ関連しているという事実は、Brendan Eich and Co の証です。だから、なぜ X や Y が JS に実装されなかったのか疑問に思うかもしれませんが、問題は、20 年前には予測できなかったことに JS を使用しているということです。

于 2013-04-28T08:33:05.367 に答える
1

さまざまな伝統的な OO 言語 (Java、C#、および C++ を含む) に関する多くの優れた本は、可能な限り「実装の継承」を使用しないように具体的にアドバイスしています。例: Joshua Bloch による効果的な Java。

奇妙なことに、実装の継承はコードに規則的な「形」を与えているように見えますが、実際には問題の解決には役立たないということです。多くの場合、長期的には問題を引き起こします。

それらの作成者は、代わりに「インターフェイスの継承」に賛成する傾向がありますが、JavaScript などのダックタイプの言語では、そのような継承を明示的に宣言する必要はありません。

また、JS では、同じ関数を複数のオブジェクトのプロパティとして割り当てるだけで、同じ関数を「再利用」できます。必要な継承のフレーバーが何であれ、何もないところから呼び出すことができます。

于 2013-04-28T08:39:13.403 に答える
1

JavaScript には実際の OOP スタイルのクラスさえありません。似たようなものをシミュレートできるだけです。

あなたの例では、次のようにして継承を実現できます

var Pawn = function(teamColor, pos) {
    Piece.call(this, teamColor, pos);
}

ただし、通常は、新しく作成されたオブジェクトではなく、関数プロトタイプにメソッドをアタッチする必要があります。その場合、たとえば CoffeeScript のように、プロトタイプ チェーンを設定することで継承をシミュレートできます。

var a, b, _ref,
  __hasProp = {}.hasOwnProperty,
  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

a = (function() {
  function a() {}

  return a;

})();

b = (function(_super) {
  __extends(b, _super);

  function b() {
    _ref = b.__super__.constructor.apply(this, arguments);
    return _ref;
  }

  return b;

})(a);
于 2013-04-28T08:39:45.997 に答える