【科学技術計算講座5-4】JavaScriptでオブジェクト指向プログラミング

前回はp5.jsでアニメーションを表示してみました。

p5.jsというJavaScriptライブラリでデータのアニメーションを表示してみます。科学技術計算講座5「粒子法(SPH法)で流体シミュレーション」の第3回目です。

今回はJavaScriptでオブジェクト指向について少しだけお話したいと思います。

オブジェクトとは

プログラミングをやっていくとオブジェクト指向という言葉がよく出てきます。オブジェクトというのは「もの」です。物体だったり、対象物だったり使う場面によって様々です。プログラミングの分野でも色々な概念で使われることがあります。

具体的なイメージで見ていきましょう。例えば「本」という「もの」があります。小説や学術書や辞書やマンガなどなど様々な本があります。これらに共通の性質は何でしょうか。

例えば、「ジャンル」という性質を持っています。小説とかマンガとか工学書といったジャンルです。他に「著者」という性質もあります。「出版社」や「出版年」もありますね。図書館を考えてみれば、ジャンルや著者などで本の書棚が分類されているのがわかります。本を検索するときには「書名」で検索するので、書名も重要な性質です。一方で、図書館ならその本を「貸し出す」「返却する」という操作を伴います。つまり、おおもとの本というのは次のような概念で表すことができます。プログラミングでは、これを「クラス(Class)」と呼んでいます。

本クラス

本のクラス

さて図書館に新しい本が入ってきた場合、その本をこの「本のクラス」に当てはめて登録します。

本オブジェクト

粒子法入門という本のオブジェクト

この登録されたものが「オブジェクト(Object)」です。書名や著者などの性質は「プロパティ」と呼ばれます。そして、この本を貸し出すときには、このオブジェクトに対して、貸し出す操作を行います。この操作のことを「メソッド」と呼びます。

オブジェクト指向とは

ここに挙げた本の性質や操作は、どの本にも共通してあります。このように、共通する性質や操作をひとまとめにしておくと何かと便利です。プログラミングで言えば、書名という変数と著者という変数が個別に管理されていると、その間の紐付けを別途行わなければなりません。また、貸し出すという操作も、本A、本B、本C...について個別にプログラムしていたらキリがないです。そこで、オブジェクトという「もの」ごとに共通の性質や操作をまとめておいて処理していこう、というのがオブジェクト指向によるプログラミングです。

※言語や開発体系によって細かなオブジェクト指向の定義は異なる場合もありますが、ざっくりしたイメージとして理解しておいてください。

JavaScriptによる具体例

イメージだけで話をするとよくわからないので、本講座でプログラミングしていくオブジェクトの例をあげて説明したいと思います。

ベクトルのクラス

例えば、粒子の位置や速度は「ベクトル」で表されます。いま2次元を考えると、ベクトルの成分はx、yの2成分です。つまり、2次元ベクトルに最低限必要なプロパティは、x、yの2つの成分になります。これをJavaScriptでプログラミングしてみましょう。

まず、ベクトルのおおもとになる「ベクトルクラス」を作ります。JavaScriptファイルとしてvector.jsというファイルに以下を書きます。

class Vector {
  constructor(x = 0, y = 0) {
    this.x = x;
    this.y = y;
  }
}

JavaScriptにはclassという構文があり、クラスを作ることができます。ここでは、クラスの名前をVectorとしています。

constructor()は、コンストラクターと呼び、このクラスを用いてオブジェクトを作った場合にプロパティを初期化するのに使われます。ここでは、this.x = xとしてプロパティ x に引数のxを代入しています。thisというのは自分自身のオブジェクトを表します。

※コンストラクターの引数が、x = 0 となっているのは、もし引数に何も入力されなかった場合には x = 0 を入力するように、という意味です。

これだけでは何のことかさっぱりわからないと思うので、ベクトルオブジェクトを実際に作ってみます。次のようにファイルに追加します。

class Vector {
  constructor(x = 0, y = 0) {
    this.x = x;
    this.y = y;
  }
}

let a = new Vector(1, 2);
let b = new Vector();
console.log(a);
console.log(b);

let a = new Vector(1, 2); の箇所は、「a という変数にVectorクラスを使って新しいオブジェクトを作る」という操作です。newの後にクラス名でオブジェクトを作ります。Vectorの引数1,2はコンストラクターの引数x,yに相当します。これで、a = (1, 2) というベクトルを作ることができます。次のbは引数がないので、上で説明したように0が代入され、b = (0, 0) というゼロベクトルが作られます。console.logでコンソールにそれぞれ出力しているので、データを見ることができます。

これまでと同様に、index.htmlを作り、<script>タグのファイル名をvector.jsにして、ブラウザで開いてください。コンソールは [Ctrl]+[Shift]+I で表示できます。

※今後も同様にJavaScriptファイルはindex.htmlをブラウザで開いて実行してください。同じなので説明は省きます。

するとコンソールに、次のようにa, b のベクトルが出力されています。それぞれx,yのプロパティに値が入っていることがわかります。

Vectorオブジェクトの結果

メソッドの定義

では次に、ベクトルに対する操作(メソッド)を定義してみます。ここでは、

  1. ベクトルの大きさを取得
  2. ベクトルどうしの引き算
  3. ベクトルの内積を計算

という3つを考えます。

vector.jsのVectorクラスに次のように追加します。

class Vector {
  constructor(x = 0, y = 0) {
    this.x = x;
    this.y = y;
  }

  magnitude() {
    return Math.sqrt(this.dot(this));
  }

  sub(v) {
    const x = this.x - v.x;
    const y = this.y - v.y;
    return new Vector(x, y);
  }

  dot(v) {
    return this.x * v.x + this.y * v.y;
  }
}

magnitude()はベクトルの大きさを計算するメソッドを定義しています。this.dot(this)は下で定義する内積(dotメソッド)で、自分自身thisの内積をとっています。そして、それの平方根をとって返しています。

sub(v)は自分自身からベクトル v を引くというメソッドです。その結果を新しいベクトルオブジェクトで返します。

dot(v)は自分とベクトル v の内積を計算して返すメソッドです。

※ this.x や v.y などの箇所ですが、 (オブジェクト).(プロパティ) でそのオブジェクトのプロパティの値を取得できます。

では、実際にメソッドを使ってみましょう。クラスの下に以下を追加して実行してみてください。

let a = new Vector(3, 4);
let b = new Vector(1, 5);
console.log(a.magnitude());
console.log(a.sub(b));
console.log(a.dot(b));

a = (3, 4)、b = (1, 5) の2つのベクトルオブジェクトを作り、メソッドを処理しています。メソッドは、

(オブジェクト).(メソッド)

のように . でつないで書きます。

大きさ: a.magnitude() → aベクトルの大きさ → 5
引き算: a.sub(b) → aベクトルからbベクトルを引く → (2, -1)ベクトル
内積:  a.dot(b) → aベクトルとbベクトルの内積 → 23

になっていると思います。

このように、ベクトルというオブジェクトのおおもとをクラスにまとめておくと管理しやすいです。本講座では、他にも粒子のクラスなども作っていきます。ベクトルより粒子の方がイメージしやすいかも知れません。粒子は、座標や速度、物性値などのプロパティを持っています。そして、粒子一つ一つを個別のオブジェクトとして考えることができます。

オブジェクト指向には、継承やカプセル化、多態性(polymorphism)といった性質が備わっていると言われますが、ここではそこまで難しい話には踏み込まないようにします。興味がある方は勉強してみてください。

まとめ

オブジェクト指向に少しふれ、JavaScriptで具体的にどのように使うか説明しました。ここでは簡単な例でしたが、大規模な開発になるとこのような手法は非常に大事になります。この講座では簡単なオブジェクトを使ってプログラムを作成していきます。

次回からはSPH法の具体的な仕組みの話に入りたいと思います。最初は流体の方程式であるNavier–Stokes方程式の紹介から始めましょう。


←前回 p5.jsでアニメーション
→次回 ナビエ=ストークス方程式の導出

全体の目次

スポンサーリンク
科学技術計算のご相談は「キャットテックラボ」へ

科学技術計算やCAEに関するご相談、計算用プログラムの開発などお困りのことは「株式会社キャットテックラボ」へお問い合わせください。

お問い合わせはこちら

フォローする