283 | | 以上が、 Java や C++ などで言うところのクラス定義に相当する、といって良いでしょう。継承を行いたい場合は、新たに定義するコンストラクタの関数名に、プロトタイプの複製をコピーしてあげれば ok です。以下のような記述になります。 |
284 | | |
285 | | {{{ |
286 | | // ダイアログオブジェクトの基本クラス |
287 | | function Dialog() {} |
288 | | Dialog.prototype = { |
289 | | "doModal": function(callback) { |
290 | | this.modal_callback = callback; |
291 | | this.createDialog(); |
| 283 | 以上が、 Java や C++ などで言うところのクラス定義に相当する、といって良いでしょう。継承を行いたい場合は、新たに定義するコンストラクタの関数名に、プロトタイプの複製をコピーしてあげれば ok です。以下は、人を表す基本クラス Human からコンストラクタとメソッドを継承し、働く人を表す派生クラス Worker を実装するサンプルです。 |
| 284 | |
| 285 | {{{ |
| 286 | function Human(name, birth, sex) { |
| 287 | if (name == null) // プロトタイプの複製をコピーする際には、このコンストラクタは何もしない |
| 288 | return; |
| 289 | this.name = name; |
| 290 | this.birth = birth instanceof Date ? birth : new Date(birth); |
| 291 | this.sex = /^m/i.test(sex) ? "male" : "female"; |
| 292 | } |
| 293 | |
| 294 | Human.prototype = { |
| 295 | "introduce": function() { |
| 296 | var message = "私の名前は" + this.name + "。" + |
| 297 | this.birth.getFullYear() + "年" + (this.birth.getMonth() + 1) + "月" + |
| 298 | this.birth.getDay() + "日生まれの" + (this.sex == "male" ? "男性" : "女性") + "です。"; |
| 299 | var message += this.makeAdditionalIntroduction(); |
| 300 | alert(message); |
293 | | "createDialog": function() { |
294 | | this.window = document.createElement("div"); |
295 | | this.window.className = "dialog"; |
296 | | var dialog_title = document.createElement("h2"); |
297 | | dialog_title.appendChild(document.createTextNode(this.title || "名称未定義")); |
298 | | document.body.appendChild(this.window); |
299 | | this.drawForm(); // 継承クラスにて実装する |
300 | | this.show(); |
301 | | }, |
302 | | "show": function(is_show) { |
303 | | is_show = typeof is_show == "boolean" ? is_show : true; |
304 | | this.window.style.display = is_show ? "block" : "none"; |
305 | | }, |
306 | | "destroyDialog": function() { |
307 | | if (!this.window) return; |
308 | | if (this.modal_callback && this.preEndModal) { |
309 | | var result = this.preEndModal(); |
310 | | if (result == null) |
311 | | return; |
312 | | if (result) |
313 | | this.modal_callback(); |
314 | | } |
315 | | if (this.preDestroyDialog) { |
316 | | if (!this.preDestroyDialog()) |
317 | | return; |
318 | | } |
319 | | document.body.removeChild(this.window); |
320 | | this.window = undefined; |
| 302 | "makeAdditionalIntroduction": function() { |
| 303 | // 基本クラスでは何もせず、空文字列を返す |
| 304 | return ""; |
324 | | function AhoDialog() { |
325 | | this.title = "あほダイアログ"; |
326 | | } |
327 | | |
328 | | AhoDialog.prototype = new Dialog(); // メンバメソッドを継承 (プロトタイプの複製をコピー) |
329 | | |
330 | | // 継承クラスの独自メソッドを記述 |
331 | | AhoDialog.prototype.drawForm = function() { |
332 | | this.dom_elems = {}; |
333 | | var p = document.createElement("p"); |
334 | | p.appendChild(document.createTextNode("あほあほ")); |
335 | | this.window.appendChild(p); |
336 | | p = document.createElement("p"); |
337 | | p.appendChild(document.createTextNode("どう思いますか? → ")); |
338 | | var input = document.createElement("input"); |
339 | | input.type = "text"; |
340 | | input.style.width = "20em"; |
341 | | p.appendChild(input); |
342 | | this.dom_elems.answer_input = input; |
343 | | this.window.appendChild(p); |
344 | | p = document.createElement("p"); |
345 | | p.style.textAlign = "center"; |
346 | | input = document.createElement("input"); |
347 | | input.type = "button"; |
348 | | input.value = "OK"; |
349 | | var that = this; |
350 | | input.onclick = function() { |
351 | | that.is_ok = true; |
352 | | that.destroyDialog(); |
353 | | }; |
354 | | p.appendChild(input); |
355 | | p.appendChild(document.createTextNode(" ")); |
356 | | input = document.createElement("input"); |
357 | | input.type = "button"; |
358 | | input.value = "キャンセル"; |
359 | | input.onclick = function() { |
360 | | that.is_ok = false; |
361 | | that.destroyDialog(); |
362 | | }; |
363 | | p.appendChild(input); |
364 | | this.window.appendChild(p); |
365 | | }; |
366 | | |
367 | | AhoDialog.prototype.preEndModal = function() { |
368 | | if (!this.is_ok) // キャンセルボタン |
369 | | return false; |
370 | | var answer = this.dom_elems.answer_input.value; |
371 | | if (answer == "") { |
372 | | alert("何か入力して下さい…。"); |
373 | | this.dom_elems.answer_input.focus(); |
374 | | return; |
375 | | } |
376 | | this.data = { |
377 | | "answer": answer |
378 | | }; |
379 | | return true; |
380 | | }; |
381 | | |
382 | | // 実際にダイアログを使用するコード例 |
383 | | var dlg = new AhoDialog(); |
384 | | dlg.doModal(function() { |
385 | | var div = document.getElementById("result_container"); |
386 | | while (div.childNodes.length > 0) |
387 | | div.removeChild(div.lastChild); |
388 | | var text = ""; |
389 | | for (int i = 0; i < 1000; i++) |
390 | | text += this.data.answer + " "; |
391 | | div.appendChild(document.createTextNode(text)); |
392 | | }); |
393 | | }}} |
| 308 | function Worker(name, birth, sex, company, roll, post) { |
| 309 | Human.call(this, name, birth, sex); // 親クラスのコンストラクタを呼び出す |
| 310 | this.company = company; |
| 311 | this.roll = roll; |
| 312 | this.post = post; |
| 313 | } |
| 314 | |
| 315 | Worker.prototype = new Human(); // クラスメソッドの継承 (プロトタイプの複製をコピー) |
| 316 | |
| 317 | // Worker 独自のメソッドを実装 |
| 318 | Worker.prototype.makeAdditionalIntroduction = function() { |
| 319 | // 自己紹介に追加する内容を返す |
| 320 | return "\n" + this.company + (typeof this.post == "string" ? "の" + this.post : "") + |
| 321 | "にて、" + this.roll + "をやっています。"; |
| 322 | }; |
| 323 | |
| 324 | var murachi = new Human("村山 俊之", new Date(1978, 1, 7), "male"); |
| 325 | murachi.introduce(); |
| 326 | |
| 327 | murachi = new Worker("村山 俊之", new Date(1978, 1, 7), "male", "株式会社はらぺこ", "代表取締役社長"); |
| 328 | murachi.introduce(); |
| 329 | }}} |
| 330 | |