1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

jsでクラスインスタンスのメンバにあるクラスのメソッドを元のクラスに派生させる小ネタ

1
Posted at

はじめに

 例えばクラスAがある別のクラスBをオブジェクトの形でメンバに持っているとする。オブジェクトに名前でクラスインスタンスを登録する。そのインスタンスのメソッドを実行する形で、クラスAのメソッドをクラスBから作りたいが、同じようなコードを書きたくない。そういうときの小ネタ。

function setup() {
	createCanvas(windowWidth, windowHeight);
	background(100);

	const obj_A = new A();
	const b1 = new B(10);
	const b2 = new B(20);
	const b3 = new B(30);

	obj_A.regist("one", b1);
	obj_A.regist("two", b2);
	obj_A.regist("three", b3);

	// obj_AのメソッドとしてBのメソッドを要素に対して実行するものを作りたいが、
	// いちいち似たようなコードを書きたくない。

	// こうする
	const methods = ["dog", "cat", "fox"];
	for(const method of methods){
		A.prototype[method] = (function(name){
			const args = [...arguments];
			args.shift();
			if(this.bs[name] === undefined){ return; }
			this.bs[name][method](...args);
		});
	}
	obj_A.dog("one");
	obj_A.cat("one", 0.1);
	obj_A.fox("one", 1000, 100);

	obj_A.dog("two");
	obj_A.cat("two", 0.2);
	obj_A.fox("two", 2000, 200);

	obj_A.dog("three");
	obj_A.cat("three", 0.3);
	obj_A.fox("three", 3000, 300);
}


class A{
	constructor(){
		this.bs = {};
	}
	regist(name, obj_B){
		this.bs[name] = obj_B;
	}
}

class B{
	constructor(x){
		this.x = x;
	}
	dog(){
		console.log(`${this.x}_わんわん`);
	}
	cat(u){
		console.log(`${this.x}_にゃーにゃー_引数${u}`);
	}
	fox(u,v){
		console.log(`${this.x}_ぎゃみゃーにゃ!ぎゃぎゃんぎゃん!!!こゃぁゃゃ!引数${u}${v}`);
	}
}

実行結果:

10_わんわん

10_にゃーにゃー_引数0.1

10_ぎゃみゃーにゃ!ぎゃぎゃんぎゃん!!!こゃぁゃゃ!引数1000と100

20_わんわん

20_にゃーにゃー_引数0.2

20_ぎゃみゃーにゃ!ぎゃぎゃんぎゃん!!!こゃぁゃゃ!引数2000と200

30_わんわん

30_にゃーにゃー_引数0.3

30_ぎゃみゃーにゃ!ぎゃぎゃんぎゃん!!!こゃぁゃゃ!引数3000と300

解説

 クラスBにはcat,dog,foxというメソッドが入っている。クラスAはとある事情でクラスBのインスタンスをオブジェクト形式で保持することになっている。そこでクラスBのメソッドを名前でインスタンスを呼び出す形で定義したい。いちいちクラスBのインスタンスを呼び出したくないので。しかし似たようなメソッド定義をつらつらと書きたくない。
 そこでprototypeを使う。

	const methods = ["dog", "cat", "fox"];
	for(const method of methods){
		A.prototype[method] = (function(name){
			const args = [...arguments];
			args.shift();
			if(this.bs[name] === undefined){ return; }
			this.bs[name][method](...args);
		});
	}

Aのprototypeに直接クラス名で関数を定義してしまう。この場合の「this」というのはAのインスタンスである。それゆえthis.bsでAのインスタンスのbsにアクセスできる。さらにそれのメソッドを実行するように書けば、実質的にクラスBのメソッドを移植できる。なお、引数が指定されている場合でも、nameの後ろに連ねる形でそのまま実行できる。便利!

おわりに

 クラス定義に慣れてしまうとprototypeで書くことを忘れてしまうんですが、こんな感じで役に立つこともあるので、両方できるといいかもしれないです。
 ここまでお読みいただいてありがとうございました。

どうでもいいネタ

 配列に対して

  const tail = (a) => a[a.length-1]

っていう関数を用意すると便利なんですが、なんかこうしなくてもいい楽な方法があったら知りたいです(どうでもいい)。

1
0
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?