JavaScript でオブジェクト指向プログラミングをするなら、UMLを使おう

日経ソフトウエア 2012年 09月号」に掲載されている「JavaScriptのわからないを解消する」という特集はおもしろい内容です。ただ、クラスベースのオブジェクト指向設計をプロトタイプベースのオブジェクト指向で実装する方法について説明するにあたって苦労している感じがありました。設計時の用語と実装時の用語の違いを分けたら、もう少しわかりやすい気がしたので、自分で書いてみました。

はじめに
オブジェクト指向プログラミングは別にオブジェクト指向プログラム言語でなくてもできるわけで、設計時にクラスやオブジェクトを表現できるようにとUMLなどが開発されています。オブジェクト指向分析をした結果をUMLでまとめてから、実際にプログラムとして実装する際に採用しているプログラミング言語に応じて、どのようにプログラムを書けばいいのかを考えれば良いわけです。

設計にはUML、実装にはプログラミング言語
UMLについては、「Object Management Group – UML」で公開されています。2012/12/30時点での最新版は「OMG Modeling and Metadata Specifications」によると、2.4.1でした。

UMLでは、class(クラス)はattribute(属性)とoperation(操作)を持ちます。実装を伴うoperationはmethod(メソッド)と呼ばれます。classのインスタンスはobject(オブジェクト)と呼ばれます。UMLを使うとオブジェクト指向プログラミングをするときに、実装言語の違いによる用語の違いについて混乱をせずに話ができるはずです。Javaのようなクラスベースのオブジェクト指向プログラミング言語ではUMLの用語とキーワードの対応づけが比較的簡単にできます。

例えば、UMLのclassを「class/UML」と表現し、Javaのclassを「class/Java」と表現するとします。すると、「class/UMLはclass/Javaと対応する」といった言い方ができます。「attribute/UMLはfield/Javaと対応する」、「operation/UMLはmethod/Javaと対応する」といった言い方もできます。このように、設計のためのUMLで定義されている用語と、実装のためのプログラミング言語で定義されている用語は同じものもあれば違うものもあるという点は理解しておく必要があります。

この点を理解できると、オブジェクト指向でプログラム設計(モデリング)をするときにはUMLで表現すれば、これをJavaのようなクラスベースのプログラミング言語で実装することもできるし、JavaScriptのようなプロトタイプベースのプログラミング言語で実装することもできるし、Cのような手続き型プログラミング言語で実装することもできる、といわれたときに、何を意味しているのかわかるようになります。なお、オブジェクト指向でプログラム設計をしたときには、オブジェクト指向のための機能を提供するプログラミング言語を使った方が楽なので、特別な理由がなければCやBASICのような手続き型プログラミング言語で複雑なオブジェクト指向のプログラムを実装することはないかもしれません。小規模なものであればCやBASICでも、いろいろな工夫をすることにより、オブジェクト指向でプログラムを実装することはできます。

話を戻しましょう。設計時の用語と実装時の用語は区別して話をするとわかりやすいはずなので、UMLの用語とJavaScriptの用語を区別して「UMLで設計したものをJavaScriptで実装するにはどうすればいいか」という視点で説明をしてみます。

class/UMLとFunctionオブジェクト/JavaScript
まず、class/UMLで例えば「UserInfo」というクラスを設計したとします。JavaScriptでは次のように実装します。class/UMLはFunctionオブジェクト/JavaScriptで表現できます。

var UserInfo = function {};

object/UMLとobject/JavaScript
class/UMLの「UserInfo」というクラスから、object/UMLの「u」を生成するためには、JavaScriptでは次のように実装します。object/JavaScriptは、new演算子を使ってFunctionオブジェクト/JavaScriptから生成します。

var u = new UserInfo();

JavaScriptのnew演算子は、指定したFunctionオブジェクト/JavaScriptからコピーを作りますから、この例では「UserInfo」というFunctionオブジェクト/JavaScriptのコピーが生成されて、uという変数へ代入されます。「UserInfo」というFunctionオブジェクト/JavaScriptがclass/UMLに対応していて、「u」という変数がobject/UMLに対応していることがわかります。ここで、「u」はFunctionオブジェクト/JavaScriptなので、JavaScriptのプログラム上では「UserInfo」と「u」は同じ型となります。class/UMLを表現するFunctionオブジェクト/JavaScriptと、object/UMLを表現するFunctionオブジェクト/JavaScriptを言語の機能を使って区別することができないので、名前で区別するといった工夫が必要になります。

よく採用される区別方法が、class/UMLを表現するFunctionオブジェクト/JavaScriptはキャメル表記(大文字で始めて、単語の区切りを大文字とする)とし、object/UMLを表現するFunctionオブジェクト/JavaScriptは小文字で始めて単語の区切りに_(アンダーバー)を入れるものになります。object/UMLを表現するFunctionオブジェクト/JavaScriptは小文字で始めて単語の区切りを大文字とする方法を採用することもあるようです。

attribute/UMLと属性/JavaScript
次にattribute/UMLを表現するにはどうすれば良いでしょう。class/UMLの「UserInfo」について、「name」というattribute/UMLを持たせることにします。この「name」というattribute/UMLは単純な属性/UMLとします(「UserInfo」というclass/UMLから生成されるobject/UMLごとに別の値を持つとします。静的な属性/UMLといった場合は、class/UMLから生成されるobject/UMLはすべて共通の属性値を持つことになります)。これをJavaScriptでは次のように実装します。

var UserInfo = function(name) {
  this.name = name;
};
var u = new UserInfo('hiro345');
alert(u.name);

attribute/UMLの単純な属性/UMLは、Functionオブジェクト/JavaScriptの属性/JavaScriptとして実装することになります。このため、Functionオブジェクト/JavaScriptの「UserInfo」では引数nameを受け取り、自分自身の属性/JavaScriptにその値を保存する処理「this.name = name;」を記述しています。

operation/UMLとFunctionオブジェクト/JavaScript
次に、operation/UMLを表現するにはどうすれば良いでしょう。operation/UMLはclass/UMLの振る舞いを表現するもので、Functionオブジェクト/JavaScriptで実装することができます。JavaScriptでは、属性/JavaScriptへFunctionオブジェクト/JavaScriptを指定できます。

class/UMLの「UserInfo」へ「alert」というoperation/UMLを追加するとしましょう。Functionオブジェクト/JavaScriptの「UserInfo」が必ず「alert」という属性/JavaScriptを持ち、かつ、それがFunctionオブジェクトであれば良いので、次のようになります。

var UserInfo = function(name) {
  this.name = name;
  this.alert = function() {
    window.alert(this.name);
  }
};
var u = new UserInfo('hiro345');
u.alert();

静的なattribute/UML、operation/UMLとprototype/JavaScript
attribute/UMLのうち静的な属性/UMLや, operation/UMLのうち静的な操作/UMLを表現するにはどうすれば良いでしょうか。JavaScriptには、prototypeという属性/JavaScriptがあるので、これを利用します。prototype/JavaScriptは、あるobject/JavaScriptからnewで生成されたobject/JavaScriptが共通で参照するオブジェクトを保持するための属性/JavaScriptですから、静的な属性/UMLや静的な操作/UMLの実装に使えるのです。

class/UMLの「UserInfo」へ「static_message」という静的な属性/UMLと、「static_alert」という静的な操作/UMLを追加するとしましょう。JavaScriptでは次のような実装となります。

var UserInfo = function(name) {
  this.name = name;
  this.alert = function() {
    window.alert(this.name);
  }
  this.prototype.static_message = "Hello";
  this.prototype.static_alert = function() {
    window.alert(this.prototype.static_message);
  }
};
var u = new UserInfo('hiro345');
u.alert();
u.prototype.static_alert();

なお、オブジェクトリテラル/JavaScriptを使ってprototype/JavaScriptの修正をすることもできます。

UserInfo.prototype = {
  static_message: 'Hello';
  static_alert: function(){
    window.alert(this.prototype.static_message);
  }
};

以上、ざっくりな説明でしたが、UMLの用語と、JavaScriptの用語を区別して説明をしてみました。いかがでしたか? 設計時と実装時とで用語を区別して考えるとわかりやすくなったでしょうか。「UMLも覚えないといけないのが大変だ」という声も聞こえてきそうですが、UMLは設計時の標準技術として普及しているものなので、知識は必要ですし、身につけていると何かと役に立つはずです。

JavaScriptについては、下記の書籍の参考になるでしょう。

プログラミング言語一般については、下記が参考になるでしょう。

同じタグの記事: JavaScript
同じタグの記事: program
同じカテゴリの記事: Program
関連書籍: JavaScript
関連書籍: program