JavaScript 第5版 - 9章 クラスとコンストラクタとプロトタイプ(3)

JavaScript 第5版、「9章 クラスとコンストラクタとプロトタイプ」の「9.4 オブジェクト共通メソッド」~「9.5 スーパークラスとサブクラス」(165~173ページ)を読み進めていきます。

9.4 オブジェクト共通メソッド

  • JavaScirptで独自のクラスを定義する場合、次のようなメソッドを定義しておくと良い。

9.4.1 toString()メソッド

  • オブジェクトを文字列に変換するためのメソッド。オブジェクトを文字列に変換する必要がある文脈では、このメソッドが自動的に呼び出される。

9.4.2 valueOf()メソッド

  • オブジェクトを基本型に変換するためのメソッド。オブジェクトが基本型に変換する必要がある文脈では、このメソッドが自動的に呼び出される。
  • オブジェクトを文字列に変換する必要がある文脈では、toString()メソッドよりも優先されることがある。そのため、場合によってはtoString()メソッドを明示的に呼び出す必要がある。

9.4.3 比較用のメソッド

  • 比較演算子によるオブジェクトの比較は、「値による」比較ではなく「参照による」比較を行うため(42ページ、3章15節を参照)、値として比較するためのメソッドを追加しておくと便利である。

9.5 スーパークラスとサブクラス

プロトタイプチェーンを利用して、スーパークラスを継承したサブクラスを定義することができます。

//スーパークラス
function Rectangle(w, h) {
    this.width = w;
    this.height = h;
}
Rectangle.prototype.area = function() { return this.width * this.height; }

// サブクラス
function PositionedRectangle(x, y, w, h) {
    // スーパークラスのコンストラクタを呼び出す。コンストラクタチェーン。
    Rectangle.call(this, w, h);
    this.x = x;
    this.y = y;
}
// サブクラスのプロトタイプオブジェクトを、スーパークラスのコンストラクタを使って明示的に生成。
// 明示的に生成しない場合、Objectの直接のサブクラスになる。
PositionedRectangle.prototype = new Rectangle();

// サブクラスに不要なプロパティはプロトタイプから削除。
delete PositionedRectangle.prototype.width;
delete PositonedRectangle.prototype.height;

// サブクラスのプロトタイプオブジェクトは、スーパークラスのインスタンスであるため、
// サブクラスのプロトタイプオブジェクト(正確には、プロトタイプオブジェクトのプロトタイプ)は、
// スーパークラスのコンストラクタ関数を参照するconstructorプロパティを持っている。
// サブクラスでは、サブクラスのコンストラクタ関数を参照するようにするため、
// サブクラスのコンストラクタ関数への参照を持つconstructorプロパティを、サブクラスのプロトタイプオブジェクトに追加。
PositionedRectangle.prototype.constructor = PositionedRectangle;

// サブクラスのインスタンスメソッドをプロトタイプに追加。
PositionedRectangle.prototype.contains = function(x, y) {
    return (x > this.x && x < this.x + this.width && y > this.y && y < this.y + this.height);
}

プロトタイプとプロトタイプチェーンの仕組みを理解できていれば、それほど悩まずに理解できると思います。

この方法でサブクラスを定義する場合に気をつけておかないとならないのは、サブクラスのプロトタイプオブジェクトはスーパークラスのインスタンスであるという点です。スーパークラスから継承されたプロパティ(widthやheight)は、プロトタイプチェーンによって、サブクラス→サブクラスのプロトタイプ=スーパークラスのインスタンス→スーパークラスのプロトタイプと参照されているにすぎません。スーパークラスから継承されたプロパティは、サブクラスのプロトタイプオブジェクトのプロトタイプのプロパティということになります。

9.5.1 コンストラクタチェーン

  • 1レベルのサブクラスしか持たない場合は、サブクラスのプロトタイプオブジェクトにsuperclassプロパティを追加する方法もある。
PositionedRectangle.prototype.superclass = Rectangle;

function PositionedRectangle(x, y, w, h) {
    this.superclass(w, h);
    this.x = x;
    this.y = y;
}

9.5.2 オーバーライドされたメソッドの呼び出し

  • サブクラスでスーパークラスのメソッドをオーバーライドする場合、元のメソッドを呼び出す形で拡張するのが普通である。これをメソッドチェーンと言う。

例えば、スーパークラスのメソッドを、メソッドチェーンを使ってサブクラスでオーバーライドするには、apply()メソッドを使ってスーパークラスのメソッド(以下のtoString()メソッドのオーバーライドの例では、スーパークラスのプロトタイプオブジェクトのメソッド)を呼び出します。

PositionedRectangle.prototype.toString = function() {
    return '(' + this.x + ',' + this.y + ') ' + Rectangle.prototype.toString.apply(this);
}

また、前述のsuperclassプロパティを使う例では、次のように書くこともできます。

PositionedRectangle.prototype.toString = function() {
    return '(' + this.x + ',' + this.y + ') ' + this.superclass.prototype.toString.apply(this);
}

コメント (0)

この記事へのコメントはまだありません。

コメントフォーム

トラックバック (0)

この記事へのトラックバックはまだありません。

この記事のトラックバックURI
http://dxd8.com/archives/88/trackback/
この記事のURI
http://dxd8.com/archives/88/