このページを一旦完成とします。Jan 11, 2014 10:00 AM.
前々節では JavaScript の配列がすでにデータとコード(関数)を保持できることを、そして前節ではクラスの作成 (コンストラクタ関数の作成) と、クラスからオブジェクト (インスタンス) を作成する方法を説明しました。これで オブジェクト指向プログラミング言語に必要な大きな要件のうち2つの説明が終わったことになります。オブジェクト指向 プログラミング言語に必要な残る要件は「継承(inheritance)」です。継承とはすでに存在しているクラスのすべてのデ ータとコードを引き継ぎ、そこに独自のデータやコードを加えて新しいクラスを作ることです。
では実際にコードを書いて説明します。前節の book.js に次のコードを追加します。前節と同じように iPhone で このサイトを見た場合を考えて本来は改行しない箇所で改行していますが適宜解釈してください。
book.js
function SubBook (name, tel, mail, note) { Book.call(this,name,tel,mail); this.note = note; this.showBook = function () { var str ='名前:'+this.name+'\n'; str += '電話:' + this.tel +'\n'; str += 'メール:' + this.mail; str += 'ノート:' + this.note; alert(str); }; }
説明
では実際に Book クラスを継承した SubBook クラスを使ってみましょう。book.js の全リストは次のようになります。
function Book(name, tel, mail) { this.name = name; this.tel = tel; this.mail = mail; this.showBook = function () { var str ='名前:'+this.name+'\n'; str += '電話:' + this.tel +'\n'; str += 'メール:' + this.mail; alert(str); }; } function SubBook (name,tel,mail,note){ Book.call(this,name,tel,mail); this.note = note; this.showBook = function(){ var str ='名前:'+this.name+'\n'; str += '電話:' + this.tel +'\n'; str += 'メール:'+this.mail+'\n'; str += 'ノート:' + this.note; alert(str); }; } var obj = new Book ('Yamada Taro', '090-1111-2222', 'taro@yamada.jp'); var obj2 = new SubBook ('Suzuki Ichiro', '090-3333-4444', 'ichiro@suzuki.jp', 'イチローと同姓同名です'); obj.showBook(); obj2.showBook();
前節で「後述します」と言っていたオブジェクトのカプセル化(隠蔽化)について説明します。
予約語 this を使ってプロパティを定義した場合、そのプロパティのアクセスレベルは public になります。つまり、 そのプロパティはグローバルとなりクラスの外部からもアクセスすることができます。これを回避するには this を 使わずにクラス内のデータを関数内のローカル変数として定義します。そしてそのローカル変数にアクセスするための ゲッターメソッドとセッターメソッドを定義します。次の capsule.js を参考にしてください。
capsule.js
function Capsule (note) { var note = note; function setNote (str) { note = str; } function getNote () { return note; } this.showNote = function () { document.write( getNote() ); }; } var obj = new Capsule ('秘密のノートです'); obj.showNote();
説明
予約語 this を使用して外部からのアクセス可能にしているのは showNote() だけです。その他のデータやコード
は var や通常の関数としてクラス内だけから参照できるようになっています。
10行目では document.write() という標準関数を呼び出しています。この関数は引数で指定した文字列を HTML
ファイルに出力する関数です。
では、この capsule.js を読み込む capsule.html を次に掲載します。そして capsule.js と capsule.html を 同じディレクトリに保存し、capsule.html をお使いの Web ブラウザで開いてください。
capsule.html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Capsule</title> </head> <body> <h1> <script type="text/javascript" src="capsule.js"> </script> </h1> </body> </html>
説明
今回はスクリプトを <body> と </body> タグの間に記述しました。document.write() で出力される 引数で指定した文字列です。Web ブラウザに文字列を表示させる場合は、通常 <body> </body> タグの間 に記述します。
追記
JavaScript の予約語を見ると public、protected、private があります。よく考えるとこれを使えばアクセスレベル を簡単に変更することができるのかもしれません。このことについては私自身への今後の課題にします。
多くのオブジェクト指向プログラミング言語では、スーパークラスを一つしか指定できません。このことを単一継承と言います 。それに対して C++ では複数のスーパークラスを指定することができ、このことを多重継承と言います。では、Java や Objective-C で複数の機能を継承したい場合はどうするのでしょうか。そのことついて用意されているのが Java では インタフェースと呼ばれるもので、Objective-C ではデリゲートやプロトコルと呼ばれるものになります。
なお JavaScript が単一継承なのか、あるいは call() メソッドを使って多重継承できるのかについては私自身への 宿題とします。
JavaScript には Objective-C のデリゲートに相当するものは最初からオブジェクトに組み込まれています。 デリゲートとは多くの場合、ユーザ(この場合のユーザとはプログラマのことではなくアプリケーションを使用している人 のことです) によるマウスやキーボードの操作にどう答えるかというメソッド集のことを指します。そして Objective -C のプロトコルとは継承を使わずにクラスにメソッドを追加する方法です。この Objective-C のプロトコルはクラス を定義するときにどういうプロトコルを採用するかを指定しなければなりません。しかし JavaScript のプロトコルは 既存のクラスに対してもメソッドを追加することができます。JavaScript では標準クラス(JavaScript に最初か 用意されているクラス) に対してもプロトコルを使用してメソッドを追加することができます。
なお、現時点では JavaScript のプロトタイプの実例の掲載は割愛します。あまり詰め込んで説明しても読者を混乱 させるだけだと思います。また現時点でプロトタイプの必要性もあまり感じません。ただユーザーからのマウスや キーボードの操作(イベント、event)を感知する能力は、JavaScript のオブジェクトには最初から組み込まれている ことは覚えておいてください。