こんにちはカイリーーです。
今回は、クラスとインスタンスを理解するために僕自身が参考にした資料をまとめました。
「オブジェクト指向」というとかなり大それた話になりそうなので(というより、完璧に理解した、の域に達しているわけではないので、あえて、こういう言い方にとどめています)、「クラス」と「インスタンス」と「ちょっとオブジェクト指向」にとどめました。
このクラスやインスタンスまたオブジェクトはSESで勤め始めたときは、全く理解できませんでした。
当時、クラスを見たときはこんな思いでした。
なんでわざわざクラスなんか使って、あっちいったり、こっちいったり、わけわかんない書き方するんだよ。
このときはクラスに分けるメリットもわからなかったため、こんなことを思っていましたが、クラスで書かれている以上、これを理解しないことには話にならない。
そんな思いで資料をあさってあさって読み漁った資料でお世話になった資料を厳選しました。
この記事の対象読者
- クラス・インスタンスってなに?
- クラスを使いたいけど意味がわからない
- 僕のように使わざるを得ない状況になってしまっている方
- どうせやるならクラスを理解したい
おすすめしない人
- プログラミングをはじめて間もない人
- クラス等を特に必要としていない人
Table of Contents
そもそもクラスとは何なのか?メリットは?
クラスを使う目的やメリットがいまいちわからない。
そんな方が多いと思う。
使わなくても動けば良いのではないか。
いや、極論問題なく動けば良いとは思う。
しかしここで、考えてみてほしい。
ぐちゃぐちゃになった部屋、平積みされた本のタワーがあるとする。
ここからONE PIECEの30巻を探してください。
といわれたら、すぐに取り出せるだろうか?
おそらく、あちこち探し回って、運良く見つかるか、見つかったとしてもかなりの時間がかかることが容易に想像できる。
プログラムにも同じことが言える、動けば良い、と思って作られたコードから出来たシステムやツールに仕様変更が生じた場合に、コードがぐちゃぐちゃになった状態のところから影響範囲を割り出して改修を加え、なおかつ、バグが出ないようにコードを書き換えるのは至難の業である。
それを解決してくれる役割の一つにクラスが存在する。
こちらの記事でも紹介されている通り、
オブジェクト指向とはコードを整理整頓する技術であり、それが根本の目的と言っても過言ではない。
オブジェクト指向でつまづく7つのポイントと処方箋
そう、コードを整理整頓してメンテナンスしやすくするのが、クラスの役割である。
昔々、1960年代ごろに手続き型プログラムと言われる、全ての手続きからアクセス可能なグローバル変数の集合体によって構成される手続き型プログラムの構成で、どこから参照され、どこを変更しなければいけないのか?といったことからバグの温床になることが問題となった「グローバル変数問題」などが指摘され、後にオブジェクト指向という考えが提唱された。
過去をたどっていくと、そういった経緯もあり、クラス(オブジェクト指向)という考えによって色々と見直された。
このクラスを使うことで、どこからでもアクセス可能だったグローバル変数を、どこからでもアクセス出来ないように、クラスの中で定義した変数に、ある書き方をしない限り、クラスの中の変数にアクセス出来ないように制限を設けたりした。
上記をすることによって、どんなメリットがあるのかというと、先に述べた、「どこからでも参照され、どこを変更したのかの影響範囲がわからない」
これを解消できる。
要するにバグの温床を最小限に留めることができるのだ。
ではクラスってどうやって使うのか?
おそらく、次に出てくる言葉はこうだと思う。
なるほど。クラスを使うメリットはわかった。ではどうやってこのクラスを使えば良いのか?
本ブログの読者さん(あまりいないかもしれないが)は、カイリーーはVBAやGASに関する記事を書いていると思っているだろうから、GASでの使い方をまとめてみたいと思う。
VBAのclassについては以下記事を参考に実際に書いてデバッグして動作確認していただくと良いかと思います。
書き方の前にクラスの概念についてもう少し説明させてほしい。
クラスとはよく様々な「物体」の設計書やひな形、などと言われる。
これだけだと、ちょっと何言ってるかわかんない。
オブジェクトとは「物」物体を表す。
クラスとは「設計書」を表す。
「物」を生み出すためには「設計書」が必要です。
これで少しわかりやすくなったか。
では、ちょっと例えを変えてみます。
突然ですが、ミニ四駆を組み立てるには何が必要でしょうか。
ニトリで買った家具を組み立るには何が必要でしょうか。
答えは「説明書」
一つのミニ四駆(プラモデル)や家具を組み上げるには、「説明書」が必要であり、それを組み上げて作られたのが「物」だ。
設計書から説明書に言葉が入れ替わっているじゃないか、と思われたと思うが、世間一般に使われているものの方がしっくり来ると思い上記を例として説明させていただいた。
ミニ四駆(プラモデル)もニトリの家具も、それぞれパーツが存在し、それを説明書を見ながら組み立てていく。
そんなイメージをしていだいていただければと思う。
クラスを理解する上で、必ず必要になってくるのが、
プロパティとメソッド。
わかりやすく言うとプロパティは変数
メソッドは関数
と思っていただくと良いかと思います。
プロパティとは属性や情報
メソッドは動作や振る舞い(物の動き)
などと言われています。
では、ミニ四駆におけるプロパティとは?メソッドとは?
以下のように定義してみました。
プロパティ
- 名前
- 重さ
- スピード
メソッド
- 走る
まとめると
ミニ四駆というクラスを定義し、
そのミニ四駆はどんな情報を持ってるのか?
どのような動作や振る舞いをするのか?
それが、プロパティ(変数)とメソッド(関数)で表すことが出来ます。
実際にプロパティに情報をいれてやるとこんな感じになると思います。
プロパティ
- 名前 = サイクロンマグナム
- 重さ = 200g
- スピード = 20km
メソッド
- 走る ()
GASクラスにおける基本構文は以下のようになります。
class クラス名 {
constructor(引数)
this._変数 = 引数
関数名(){
}
}
constructorとはクラスをnewしたときに自動的によびだされて実行されるメソッドです。
VBAでいうinitializeです。
「this.」というのは、thisとは自分自身を指すであったり、
thisキーワードは、その関数・メソッドとプロパティとして持つオブジェクトへの参照です。
などと書かれているものがあるのですが、ちょっとむずかしい。
あくまで僕がthisを日本語化した場合は
このクラスのプロパティは○○です。
そのプロパティにAという変数の値を代入します。
そしてそのプロパティの値を使う場合には、this._変数とすることでプロパティ値を参照することが出来ます。
と解釈しています。
メソッドを参照する場合も同じです。
このthis問題の説明がなかなか難しいですが、自分なりにしっかり理解して解釈するとしたら上記のように考えるようにしています。
ここまで説明して、先程の基本構文に日本語で定義していたプロパティ値を設定し、走る動作を当てはめると以下のようになります。
class Mini4wd {
constructor(machineName, weight, speed) {
//プロパティ値(情報)
this._name = machineName; //名前
this._weight = weight; //重さ
this._speed = speed; //スピード
}
//走るという動作
machineRun() {
return this._name + "は" + "時速" + this._speed + "km" + "で走ります。"
}
}
function main () {
const machineName = "サイクロンマグナム";
const weight = 200;
const speed = 20;
const magnum = new Mini4wd (machineName, weight, speed);
console.log(magnum.machineRun());
//結果:サイクロンマグナムは時速20kmで走ります。
}
処理の流れは以下の様になります。
このメイン処理とクラスを見てもらうと分かる通り、
クラスはミニ四駆に関する「情報」と「動作」の内容が記載されています。
このミニ四駆クラスから生み出された具体的なサイクロンマグナムがインスタンスとなる。
ミニ四駆の設計書(説明書)から、サイクロンマグナムという物体を生み出した。
もちろんミニ四駆クラスからは別のインスタンスを生み出すことができる。
例えばハリケーンソニックをインスタンス化しようとすると以下のようになる。
let machineName_2 = "ハリケーンソニック";
let weight_2 = 200;
let speed_2 = 15;
const sonic = new Mini4wd_2 (machineName_2, weight_2, speed_2);
このmagnumやsonicなどの具体的なミニ四駆の定義がインスタンスとなる。
厳密には、値の妥当性をチェックするために、以下のようにチェック機能を働かせる必要もあります。
class Mini4wd_2 {
// プロパティ値(値のセット)
constructor(machineName, weight, speed) {
try {
// 車体重量がマイナスの場合エラー
if (weight <= 0) {
throw new Error("車体重量がレギュレーション違反です");
} else {
this._name = machineName; //名前
this._weight = weight;//重量
this._speed = speed; //スピード
}
}catch(e){
Browser.msgBox("エラー:" + e.message);
}
}
if (weight <= 0)として0以下はありえないので、その場合はレギュレーションに違反している旨の例外エラーを発生させています。(余談:公式のミニ四駆のルールの重量は90g以上である必要があるようです)
1g以上であれば、プロパティ値に格納できる。(本来1gもありえないが、例のため、0g以下の場合は、という仕様にさせていただいた。)
このような仕組みにすると何が良いのかというと、クラス宣言をした入り口で異常値を検知し、エラーで止めることができるというメリットがある。
例えば、テキストボックス等でユーザーに入力をしてもらうようなシステムの場合、意図的にマイナスの値を入れられることを考慮すると、プロパティの値をセットする前にバリデーションを働かせて異常値を検知させる必要があります。
ここまでクラス、インスタンス、プロパティ・メソッドについて説明してきました。
あくまでこの記事はクラスを定義して使用する上での最低限の内容について記述しています。
上記内容をエヴァを使ってJavaを使って、スレッドのやり取りでオブジェクト指向について説明している掲示板が以下です。
あくまで概念を理解するものであるため、オブジェクト指向とは?の部分をスキマ時間の読み物として読んで頂くと良いかと思います。
そして、次にご紹介する記事が僕がクラスを理解する上で、何十回と読み直した記事です。
こちらの記事では序盤、
クラスとは変数と関数の集まりであり、データの「保持」と「処理」が可能
とおっしゃってます。
簡潔にまとめるとそうだと思います。
それが、クラス内では変数のことを「プロパティ」と呼び、
関数のことを「メソッド」と呼んでいます。
もう一度GASのクラスの基本構文の見てみましょう。
class クラス名 {
constructor(引数)
this._変数 = 引数
関数名(){
}
}
クラス内で書かれているものなので、記事の通り呼び名を変えてみましょう。
class クラス名 {
constructor(引数)
this._プロパティ = 引数
メソッド(){
}
}
こうなります。
これがいわゆる設計図の基本の型となります。
main()の処理でconst magnum = new Mini4wd();
とすることでマグナムのインスタンスが作られ、magnum. メソッド()
とすることでクラスへアクセスし、プロパティ、メソッドを扱って処理を行います。
magnum. メソッド()とは「マグナム」の「処理」を指しています。
こちらの記事にオブジェクト指向のコードを書く上での基礎が集約されています。
言語はPHPですが、PHPは比較的理解しやすい言語なので、この記事の言っている内容がある程度理解できるようになれば、VBAでのクラスにおいても理解の手助けになるかもしれません。
僕の場合、VBAのクラスがどうしても初め理解できず、別言語でわかりやすく説明されている記事はないか?と思いたどり着いたものがこちらでした。
もちろん理解するためには、別言語でも書いてコードを実行して、処理の流れを追うことで理解のスピードも早くなると思っています。
ぜひ一読、いや、何回も読んでいただければと思います。
メモリーの話
最後にメモリーの話をしておきたいと思います。
基本的なPCの仕組みはメモリーとディスクの関係性にあります。
ディスクに記憶されたプログラムがメモリーにロードされてから実行されます。
図にすると以下のような感じです。
ではこれが一体クラスと何の関係があるの?
その関係性ついては以下の動画を御覧ください。
クラスを定義すると、クラス内に記述された情報を保持するために、どの程度のメモリーを確保しなければならないのか?
実際に確保された「物」=メモリそのものがインスタンスである
C言語を書いたことがない僕は、このメモリを意識してクラスを書いていなかったのですが、実際には、ハードディスクからプログラムがロードされ、どこの番地に必要な分のメモリを確保する処理が行われている、というのを理解しておく必要がある。
また、上記の動画を見た上で次の記事を読むと、言っていることの理解が進みます。
正直なところ、このメモリの概念については僕自身まだまだ理解・研究がしきれていないため、今後の課題です。
こちらの方々が説明されているようなレベルに達するまでは、もっと深堀りして行く必要がありそうです。
今回の記事はここまでです。
ここまで読んでいただきありがとうございました。
ご意見ご感想ございましたら、TwitterDM等でお知らせいただければと思います。
\無料コンテンツを配布しております/
毎日エンジニアとして勉強をしているのに
- コードが読めるようにならない
- コードを書くなんてもってのほか
- 環境構築ができない(そもそも何をやっているのかわからない)
- >毎日できない自分に嫌気が差す
そんな毎日に悩みを抱えている方
もしかしたら間違った勉強方法をしているかもしれません。
エンジニアとして生きていくための正しい勉強とは
一体何でしょうか?
以下からご確認ください