関数をマスターする (4/5)
作成:2016-04-29 09:49
更新:2016-04-29 09:49
更新:2016-04-29 09:49
■ジェネリック(総称型)
引数や返値を利用する場合、注意しておきたいのは「タイプ」です。引数や返値では、タイプをきちんと指定して処理するのがTypeScriptの基本です。では、「複数のタイプに対応したいとき」はどうすればいいのでしょう。
例えば、引数の値をすべて+で加算していく関数を考えてみましょう。これ、引数は数字だな、と考えるかもしれません。が、JavaScript(= TypeScript)ではテキストも+でつなげることができます。このとき、「数字なら足し算し、テキストなら値をつなげる関数」はどうやってつくればいいのでしょう。
実際に、そのサンプルを下にあげておきましょう。これを見ながら、今回のポイントを説明しましょう。ここでは、addItems<string>("One", "Two", "Three")とか、addItems<number>(1, 2, 3, 4, 5)というようにしてaddItems関数を呼び出しています。片方の引数はテキスト、もう片方は整数ですね。まったくタイプは違いますが、どちらもちゃんと動きます。
ここでは、関数を以下のような形で定義してあります。
addItemsの後に、<T>というものがついています。また引数は可変引数argを用意してありますが、これもArray<T>というタイプが指定されています。Arrayは配列オブジェクトですが、この<T>というのは何でしょうか?
これは、「ジェネリクス」と呼ばれるものです。ジェネリクスは、「総称型」などとも呼ばれます。これは、様々なタイプを総称するのに使われるものです。わかりやすくいえば、「この<T>は、どんなタイプでも当てはまるワイルドカードのようなもの」なのです。numberでもstringでもbooleanでも、なんでもこの<T>に当てはめることができる、それがジェネリクスです。
引数や返値に、この<T>を使う場合、関数名の後に「これはジェネリクスを利用してますよ」ということを示すために<T>を付けることになっています。そして実際に関数を呼び出す際には、この<T>のTのところに、利用するタイプを記述してやります。
実際にこのaddItemsが使われているところを見てみましょう。こうなっていますね。
テキストの値を引数として渡す場合は、 addItems<string>(……)となっていますね。そしてnumber値を渡す場合は、addItems<number>(……)となっています。こんな具合に、ジェネリクスを利用してどんなタイプの値を渡すかを<>に指定してやります。
では、渡された引数の値はどうやって処理されているのでしょう。どんなタイプの値が渡されるのかわからないのですから、タイプに応じた処理が行えないといけません。ここでは、numberとstringの場合は加算処理をし、それ以外のタイプではnullを返すようにしてあります。これは、以下のような形で処理をしています。
「typeof」は、値のタイプを調べる関数ですね。これでタイプを調べ、その値が何かによって処理を行っていたわけです。これで、さまざまなタイプの引数や返値を処理するジェネリクスの基本的な使い方がわかりましたね!
例えば、引数の値をすべて+で加算していく関数を考えてみましょう。これ、引数は数字だな、と考えるかもしれません。が、JavaScript(= TypeScript)ではテキストも+でつなげることができます。このとき、「数字なら足し算し、テキストなら値をつなげる関数」はどうやってつくればいいのでしょう。
実際に、そのサンプルを下にあげておきましょう。これを見ながら、今回のポイントを説明しましょう。ここでは、addItems<string>("One", "Two", "Three")とか、addItems<number>(1, 2, 3, 4, 5)というようにしてaddItems関数を呼び出しています。片方の引数はテキスト、もう片方は整数ですね。まったくタイプは違いますが、どちらもちゃんと動きます。
ここでは、関数を以下のような形で定義してあります。
function addItems<T>(...arg:Array<T>): T {……}
addItemsの後に、<T>というものがついています。また引数は可変引数argを用意してありますが、これもArray<T>というタイプが指定されています。Arrayは配列オブジェクトですが、この<T>というのは何でしょうか?
これは、「ジェネリクス」と呼ばれるものです。ジェネリクスは、「総称型」などとも呼ばれます。これは、様々なタイプを総称するのに使われるものです。わかりやすくいえば、「この<T>は、どんなタイプでも当てはまるワイルドカードのようなもの」なのです。numberでもstringでもbooleanでも、なんでもこの<T>に当てはめることができる、それがジェネリクスです。
引数や返値に、この<T>を使う場合、関数名の後に「これはジェネリクスを利用してますよ」ということを示すために<T>を付けることになっています。そして実際に関数を呼び出す際には、この<T>のTのところに、利用するタイプを記述してやります。
実際にこのaddItemsが使われているところを見てみましょう。こうなっていますね。
let out1:string = addItems<string>("One", "Two", "Three");
let out2:number = addItems<number>(1, 2, 3, 4, 5);
let out3 = addItems<boolean>(true, false);
テキストの値を引数として渡す場合は、 addItems<string>(……)となっていますね。そしてnumber値を渡す場合は、addItems<number>(……)となっています。こんな具合に、ジェネリクスを利用してどんなタイプの値を渡すかを<>に指定してやります。
では、渡された引数の値はどうやって処理されているのでしょう。どんなタイプの値が渡されるのかわからないのですから、タイプに応じた処理が行えないといけません。ここでは、numberとstringの場合は加算処理をし、それ以外のタイプではnullを返すようにしてあります。これは、以下のような形で処理をしています。
switch(typeof arg[0]){
case 'number':
……number型の処理……
case 'string'
……string型の処理……
default:
……それ以外の場合の処理……
}
「typeof」は、値のタイプを調べる関数ですね。これでタイプを調べ、その値が何かによって処理を行っていたわけです。これで、さまざまなタイプの引数や返値を処理するジェネリクスの基本的な使い方がわかりましたね!
(by. SYODA-Tuyano.)
※プログラムリストが表示されない場合
AddBlockなどの広告ブロックツールがONになっていると、プログラムリスト等が表示されない場合があります。これらのツールをOFFにしてみてください。
●プログラム・リスト●
function addItems<T>(...arg:Array<T>): T { let res; switch(typeof arg[0]){ case 'number': res = 0; break; case 'string': res = '' break; default: return null; } for(let i = 0;i < arg.length;i++){ res += arg[i]; } return res; } let out1:string = addItems<string>("One", "Two", "Three"); document.write(out1); document.write('<br>'); let out2:number = addItems<number>(1, 2, 3, 4, 5); document.write(out2.toString()); document.write('<br>'); let out3 = addItems<boolean>(true, false); document.write(out3.toString());
※関連コンテンツ