この記事を書こうと思った理由
プログラミング学習を始めたとき、クラスとインスタンスの関係について勉強したときに、???となったことがあり、もし同じような方がいればなと思い書いていこうと思います。
よく見かけるクラスとインスタンスの説明
まずは、よくサイトで見かけるクラスとインスタンスの関係について見ていき、実際のコードと照らし合わせてみましょう。
クラスとインスタンスの関係
🔳クラス
オブジェクトの設計書、または設計図のようなものです。
この中に、プロパティやメソッドが記載されています。
🔳インスタンス
クラスから生成された実体のことです。
クラスが車の設計図だとすれば、インスタンスは車の実体です。
なので図で表すとこのような形になります。
設計書(クラス)から、車(インスタンス)が生成されています。
ここまではプログラミングを学習したばかりの私にとっても理解ができました。
「なるほど。。確かにクラスからインスタンスというものができるんだな。。」と
実際のコードと照らし合わせてみよう
次は、実際のコードと照らし合わせていきましょう。
(私が最初に学習した時に理解できなくなったのは、ここからです。。)
<?php class Car { // プロパティ public $color; // コンストラクタ public function __construct($color) { $this->color = $color; } // メソッド public function getColor() { return $this->color; } } ?>
<?php
// 赤色の車のインスタンスを作成
$redCar = new Car("red");
echo $redCar->getColor(); // "red"を出力
// 青色の車のインスタンスを作成
$blueCar = new Car("blue");
echo $blueCar->getColor(); // "blue"を出力
?>
実際に先ほどの設計書(クラス)と車(インスタンス)をコードに起こしてみました。
確かに、赤色と青色の車が実装されているコードになっています。
この時、皆さんはすぐ理解できましたか?
私は、頭の中が????で埋めつくされたことを覚えています。
なぜ、私が理解できない!と思ってしまったのかというと、先ほどのイラストを用いて説明してくれたものと実際のコードが、結びつかなかったからです。
難しいものを抽象的に理解しようとすると、現実(コード)に向き合った際に理解できなくなってしまうのは当たり前だと思います。
では、今回はメモリからこのクラスとインスタンスの違いについて紐解いていきましょう。
メモリから「クラス」と「インスタンス」の違いについて考える
まずは、メモリについて紹介していきます
メモリについて
今回は一時的に確保されるメモリ領域のスタック領域とヒープ領域について説明します。
🔳スタック領域:最後に確保した順に開放する
スタック領域は、確保したのとは逆の順番で解放するのが特徴です。たとえば、A、B、Cの順に確保した場合、解放するのはC、B、Aの順となります。下から積み上げた荷物を、上から取り除いていく様子をイメージするとわかりやすいでしょう。また、スタック領域はコンパイラやOSによってソフトウェアへの割り当てを決めるのも特徴です。割り当ては、あるデータについて、保存が必要な期間だけメモリ領域を確保し、不要になったら解放するように行われます。
🔳ヒープ領域:任意の順序で確保・解放する
スタック領域が下から順番に積み上げていくのに対し、ヒープ領域には順序がありません。ヒープとは山積みという意味であり、その名のとおり領域を山積みにします。つまり、どのような順序で確保・解放するかは、ソフトウェア側で自由に決められるということです。そのため、ヒープ領域は柔軟性が高いのが特徴です。
https://it-trend.jp/development_tools/article/32-0041
これら二つのメモリ領域は、クラスとインスタンスの概念を理解する上で重要となってきます。
クラスとインスタンスの違いについて
前置きが長くなってしまいましたが、ここからクラスとインスタンスの違いについてメモリ上から説明していきます。
今回説明に使用するコードは先ほど使用したコードです。
<?php
class Car {
// プロパティ
public $color;
// コンストラクタ
public function __construct($color) {
$this->color = $color;
}
// メソッド
public function getColor() {
return $this->color;
}
}
?>
<?php
// 赤色の車のインスタンスを作成
$redCar = new Car("red");
echo $redCar->getColor(); // "red"を出力
// 青色の車のインスタンスを作成
$blueCar = new Car("blue");
echo $blueCar->getColor(); // "blue"を出力
?>
「 new Car(“red”);」って何をしているの?
まず最初に、new Car(“red”)という処理が実行されます(①)。すると、次にディスク上に存在しているCar classが記載されているコードがヒープ領域にコピーされ、インスタンスを生成します。そして、ヒープ領域において200番というメモリアドレスが割り振られます(②)。
私たちがインスタンスと呼んでいるものは、ヒープ領域に存在しているメモリアドレス上にあるクラス情報のことです。よく、クラスは設計書であり、インスタンスはその設計書をもとに実体を作ったものだという説明がありますが、この実体の正体はメモリアドレスです。
「$redCar」って何しているの?
まず、$redCarという変数に対して、スタック領域にメモリが確保されます。
そして、100番地というメモリアドレスが与えられます。
つまり、$redCarという変数は、スタック領域100番地の情報を持っています。
$redCar = new Car(“red”); って何しているの?
文字の通り、左辺であるnew Car(“red”)の内容が、右辺の$redCarに代入されます。
その結果、変数である$redCarはスタック領域である100番地の情報を持っています。
この番地には、ヒープ領域の200番地の情報が入っています。
そして、ヒープ領域にはcarクラスから作られたインスタンスが入っています。
といった流れになります。
まとめ
今回は、クラスとインスタンスの違いについてメモリからひも解いてみました。
どうでしょうか?かわいらしいイラストを用いた説明より、メモリ上どうなっているかに着目していくとより分かりやすかったのではないでしょうか?
結論として、「クラス」に実体がないといわれているのはメモリが確保されていないからだということが分かりました。また、「インスタンス」がクラスから作られる実体と表現されるのは、クラスのコード情報をコピーしてヒープ領域にメモリが確保されるからということが分かりました。
コメント
You actually make it seem so easy along with your presentation however I to find this matter to
be really one thing that I believe I would by no means understand.
It kind of feels too complex and extremely vast for me.
I am having a look ahead to your next publish, I will try to get the cling of it!
Thank you !