最近、昔書いた物をあれこれまとめ中です。 折角編集したのでここに、さらします。 オブジェクト指向を説明するのに使ったもの。 JavaScriptとJavaを説明に使っています。Object Oriented JavaScriptって奴です。 途中変なテンションになっているのはご容赦下さい。

オブジェクト指向についてのおさらい

まず、オブジェクト指向についておさらい。 オブジェクト指向言語Javaで書いてサンプルを見てみましょう。
class Dog {
	String name;
	Dog(String name) {
		this.name= name;
	}
	String bark() {
		return name + "[わん]";
	}
}
public class BarkCall {
	public static void main(String[] args) {
		Dog pochi = new Dog("ポチ");
		Dog taro = new Dog("タロー");
		System.out.println(pochi.bark());
		System.out.println(taro.bark());
	}
}
実行結果はこうなります。
[oojs azazel]$ java BarkCall
ポチ[わん]
タロー[わん]
シンプルなオブジェクト指向の一例です。 Dogクラスのインスタンスである”pochi”と"taro"に泣けとメッセジーを送ると、自分の名前と共に、[わん]と泣きます。 コレはあたかも、現実世界の犬に”お手!”とメッセージを送っているようなモノです。 次にオブジェクト指向の神髄の一つ、ポリモフィズム(多態性)について見てみましょう。
abstract class Animal {
	abstract String cry(); 
}
class Dog extends Animal{
	String cry() {
		return "わん!";
	}
}
class Baby extends Animal{
	String cry() {
		return "おぎゃー!";
	}
}
class Cat extends Animal{
	String cry() {
		return "にゃー!";
	}
}
public class CryCall {
	public static void main(String[] args) {
		Animal dog = new Dog();
		Animal baby = new Baby();
		Animal cat = new Cat();
		System.out.println(dog.cry());
		System.out.println(baby.cry());
		System.out.println(cat.cry());
	}
}
ポリモフィズムのメリットは2点あります。 一点目はAnimalクラスに実装の無い抽象メソッド、cry()を定義している点。 こうすることで、Animalを継承したクラスには、cry()メソッドを実装する事を強制出来ます。 つまり、必ず必要なインターフェースを統一出来るのです。 二点目は継承してクラスの実体(インスタンス)は、スーパークラスの型に代入出来る点です。 こうすることで、インスタンスを利用する側は、今、「泣け!」とメッセージを送った相手が、Dogであるのか、Babyであるのか、Catであるのか意識する必要がないのです。 これは、あたかも「現実のモノに対してメッセージを送る」というように、現実社会のあり方に沿った自然な書き方なんです。 オブジェクト指向万歳! ・・・・ なんて説明をよく聞きますけど、理解できますか? 私は出来ませんでした。そもそも「動物」って動物を現実社会で見たことは有りません。 私の考えるオブジェクト指向のメリットは非常に単純です。 「コードを書く量を減らす->修正が楽になる=開発が楽になる。」 それだけです。 オブジェクト指向の神髄とメリットを実感するなら、デザインパターンを学ぶのが良いと思いますが、それはまた次回に。

OOJS(Object Oriented JavaScript)

とにかく、JavaScriptでオブジェクト指向を実装してみましょう。
単純なクラスの例
基本的に変わらないのですが、ちょっとだけ癖が有ります。 今度は単純にDogクラスを実装してみます。
<html>
<body>
<script type="text/javascript">
function Dog(_name) {
	this.name = _name;
}
var dog = new Dog("ポチ");
document.writeln(dog.name);
</script>
</body>
</html>
此処まではほとんどかわりませんよね? ではbarkメソッドを追加してみましょう。
<html>
<body>
<script type="text/javascript">
function Dog(_name) {
	this.name = _name;
	this.bark = bark
}
function bark() {
	document.writeln(dog.name + " : わん!")
}
var dog = new Dog("ポチ");
dog.bark();
</script>
</body>
</html>
Javaの場合と違うのは、クラス、メソッドという概念ではなく、bark()というファンクションを、Dogのthis.dogというプロパティに代入している事です。 また、JavaScriptの無名関数という方法で以下の用に書くことも出来ます。
<html>
<body>
<script type="text/javascript">
function Dog(_name) {
	this.name = _name;
	this.bark = function () {
		document.writeln(dog.name + " : わん!");
	}
}
var dog = new Dog("ポチ");
dog.bark();
</script>
</body>
</html>
また、JavaScriptならではの特徴も有ります。 「メンバ(メソッド)の後付」です。下記コードを見てください。
<html>
<body>
<script type="text/javascript">
var obj = new Object();
obj.bark =  function () {
	document.writeln("  わん!");
}
obj.bark();
</script>
</body>
</html>
いかがでしょう? クラス、メソッドという概念ではなく、あくまで、プロパティに関数を代入しているだけというのがおわかり頂けましたか? では、もう一つ実験です。 今度はオブジェクトを2つ作ってみましょう。 きっと上手く行くはずです。
<html>
<body>
<script type="text/javascript">
var obj1 = new Object();
obj1.bark =  function () {
	document.writeln("  わん!");
}
var obj2 = new Object();
obj2.bark(); // ここでエラーになる
</script>
</body>
</html>
エラー!? なんて事でしょう。 もう絶望です。JavaScriptではオブジェクト指向を実装出来ないのでしょうか?
prototypeという解法
いいえ、そんな事は有りません。 上記のコードでは、インスタンスであるobj1のプロパティに対してのみbarkメソッドを追加していました。 クラスであるObjectはこの時点では、変化が及んでいないのでObjectをインスタンス化したobj2には、barkプロパティが存在しないためエラーとなってしまいました。 ではどうすれば良いのでしょうか? JavaScriptにはprototypeという特殊なプロパティが有ります。
<html>
<body>
<script type="text/javascript">
Object.prototype.bark =  function () {
	document.writeln(" わん!");
}
var obj1 = new Object();
var obj2 = new Object();
obj1.bark(); 
obj2.bark(); 
</script>
</body>
</html>
いかがでしょう? 問題なく表示されましたね。 JavaScriptの決まりごとで、prototypeプロパティには、prototypeオブジェクトという特殊なオブジェクトが代入されます。 prototypeプロパティは、その関数をインスタンス化した場合のインスタンス参照(prototypeオブジェクト)が代入される事になっています。 つまり、prototypeプロパティが宣言された関数から生成されたインスタンス全てに影響が及びます。 現実的な事をいえば、Object関数は全てのオブジェクトの基底関数(クラス)ですので、下手にプロパティを追加すると、全てのインスタンスに影響が及んでしまいます。 あまり不用意に使うべきでは無いでしょう。