ywork2020.com

Title

クラスを学べばオブジェクトの設計図を作成出来る

オブジェクト指向のクラスとは

はじめに申し上げておきますが、HTMLの属性やCSSのセレクタのclassとは別物であり、オブジェクト指向プログラミング言語でいうクラスのことを説明しています。
クラスとはオブジェクトを定義する設計図です。クラスを元にコンストラクタを使ってオブジェクトのインスタンス化を行うという流れになります。

サンプルコード1 : オブジェクト.プロパティの定義

例として今日の西暦年月日をプロパティから日本語表示で取得出来るクラスを作成してみます。
<script>
	function JapToday(){			//コンストラクタを定義
		let today = new Date();
		let arrDayName = new Array('日', '月', '火', '水', '木', '金', '土');
		this.year = today.getFullYear() + '年';
		this.month = (today.getMonth() + 1) + '月';
		this.day = today.getDate() + '日';
		this.dayName = arrDayName[today.getDay()];
	}

	let japToday = new JapToday();	//new コンストラクタでオブジェクトをインスタンス化
	document.write(				//オブジェクト.プロパティから値を取得表示
		japToday.year,
		japToday.month,
		japToday.day,
		'('+japToday.dayName+')'
	);
</script>
サンプルコード1の実行結果

サンプルコード2 : オブジェクト.プロパティの定義

普段は全角文字などを使ったコードは書かないと思いますが、「初学 = 理解しやすく」ということで、 例として全角文字を使ったコードでクラスを作成してみます。ちなみに問題なく動作すると思います。

<script>
	function 個人(名前,年齢,性別){		//コンストラクタを定義
		this.名前 = 名前;
		this.年齢 = 年齢;
		this.性別 = 性別;
	}

	let こじん1 = new 個人('一郎',22,'男性');		//new コンストラクタでオブジェクトをインスタンス化
	let こじん2 = new 個人('花子',20,'女性');		//new コンストラクタでオブジェクトをインスタンス化
	document.write('こじん1の名前は[',こじん1.名前,']です。<br>');
	document.write('こじん2の性別は[',こじん2.性別,']です。');
</script>
サンプルコード2の実行結果

サンプルコード3 : オブジェクト.メソッドの定義 (コンストラクタ内定義)

サンプルコード2の続きで全角文字込みのコードで記述してみます。
この記述方法は理解しやすく、小規模な処理なら問題なく利用できます。が、大規模な処理ではメモリー消費が多くなる可能性があるのでお勧めは出来ません。
が、一応の理解として参考にして下さい。

<script>
	let 個人 = function(名前,年齢,性別){
		this.名前 = 名前;
		this.年齢 = 年齢;
		this.性別 = 性別;

		this.名前設定 = function(名前){
			this.名前 = 名前;
		}
		this.年齢設定 = function(年齢){
			this.年齢 = 年齢;
		}
		this.性別設定 = function(性別){
			this.性別 = 性別;
		}
	}

	let こじん3 = new 個人();
	こじん3.名前設定('次郎');
	こじん3.年齢設定(16);
	こじん3.性別設定('男性')
	document.write(こじん3.名前,'<br>');
	document.write(こじん3.年齢,'<br>');
	document.write(こじん3.性別);
</script>
サンプルコード3の実行結果

サンプルコード4 : オブジェクト.メソッドの参照を定義 (prototype定義)

サンプルコード3のメモリー消費を抑えた方法がprototype(プロトタイプ)プロパティを利用した形になります。
インスタンス化されたオブジェクトが実体化されたプロパティを実装するのは当たり前のことですが、メソッドまで実体化する必要はありません。
メソッド(命令文)は値を格納する為のものでは無く、データの処理工程を定義したものなので、常に同じ動きの設計図をオブジェクトが生成される度に実体化に加えなくても設計図の参照さえ出来ればよいということになります。
ですので、サンプルコード4ではサンプルコード3のメソッドの定義部分をコンストラクタの外でprototypeプロパティを利用して設計図を参照するように定義しています。

<script>
	let 個人 = function(名前,年齢,性別){
		this.名前 = 名前;
		this.年齢 = 年齢;
		this.性別 = 性別;
	}

	個人.prototype.名前設定 = function(名前){
			this.名前 = 名前;
	}
	個人.prototype.年齢設定 = function(年齢){
			this.年齢 = 年齢;
	}
	個人.prototype.性別設定 = function(性別){
		this.性別 = 性別;
	}

	let こじん4 = new 個人();
	こじん4.名前設定('弥生');
	こじん4.年齢設定(14);
	こじん4.性別設定('女性')
	document.write(こじん4.名前,'<br>');
	document.write(こじん4.年齢,'<br>');
	document.write(こじん4.性別);
</script>
サンプルコード4の実行結果

サンプルコード5 : コンストラクタの引数制御

次の例は引数が全て満たされていない場合と、逆に多く設定した場合の処理例です。if制御文で条件によって処理を変更しています。
引数が空の場合、その値を参照するとundefined(参照できない)が戻り値として返ってきます。またarguments.lengthで引数の数が返ってくるので、これを利用して処理を分岐しています。

<script>
	let 個人 = function(名前,年齢,性別){
		if(名前===undefined){名前='匿名'}
		if(年齢===undefined){年齢='不明'}
		if(性別===undefined){性別='不明'}
		if(arguments.length>3){window.alert('引数が上限を超えています。')}

		this.名前 = 名前;
		this.年齢 = 年齢;
		this.性別 = 性別;
	}

	let こじん5 = new 個人("三郎",12);
	document.write(こじん5.名前,'<br>');
	document.write(こじん5.年齢,'<br>');
	document.write(こじん5.性別);
</script>
サンプルコード5の実行結果

サンプルコード6 : ECMAScript 2015以降の解りやすくなったクラス定義 (糖衣構文)

このサンプルはECMAScript 2015(ES6)から導入されたクラスの定義構文で記述しています。クラスを定義しているのが一目で解りやすくなります。
このサンプルでは[個人]というコンストラクタから継承クラスを作成しています。[個人改]には年齢を判別するプロパティを追加実装しています。

<script>
	class 個人{
		constructor(名前,年齢,性別){
			this.名前 = 名前;
			this.年齢 = 年齢;
			this.性別 = 性別;
		}
	}

	class 個人改 extends 個人{
		get 成人判別(){
			this.判別行程();
			return(this.結果);
		}
		判別行程(){
			if(this.年齢>19){
				this.結果 = '成人';
			}
			else{
				this.結果 = '未成年';
			}
		}
	}

	let こじん6 = new 個人改('里子',12,'女性');
	document.write(こじん6.名前,"<br>");
	document.write(こじん6.年齢,"<br>");
	document.write(こじん6.性別,"<br>");
	document.write(こじん6.成人判別);
</script>
サンプルコード6の実行結果

関連のあるページ