「オブジェクト指向や設計ってなんなのかさっぱりわからない」
「クラスや継承、ポリモーフィズムって何?」
そうお考えの方は、『オブジェクト指向でなぜ作るか』を一読されることをおすすめします。
僕は、未経験からWebエンジニアとして就職し、現在1ヶ月目です。
業務を開始すると、膨大なコードの量に圧倒されました。
それぞれのファイルがどのような関連性を持つのかがわからず、苦労をしています。
しかし、クラスの概念や継承関係を紐解くことで、徐々にですが理解できるようになってきました。
これらクラスに関する考えは、『オブジェクト指向でなぜ作るか』を読んだことで、レベルアップしたなと感じています。
基本的にどのアプリケーションもオブジェクト指向の考えをもとに開発されているので、既存のアプリケーションがどのような意図で作られているのかが、徐々にですが理解できるようになってきたのです。
ちなみに、『オブジェクト指向でなぜ作るか』のサンプルプログラムはJavaが利用されていますがプログラムの難易度は低いため、Java以外の学習者の方でも理解できるレベルです。
私はRuby学習者ですが問題ありませんでしたよ。
本記事では、『オブジェクト指向でなぜ作るか』を読んで、「特にプログラミングにについて役立つ」と思った点に絞り、まとめめていきます。
オブジェクト志向でなぜ作るか』を読むにあたっての前提
各言語のクラスや継承の仕組みは理解しておく必要があります。Rubyでいえば、『プロを目指す人のためのRuby入門』などで、「クラス」や「モジュール」について最低限理解しておかないと、これらの機能がなんのためにあるのかまで考えが及ばなくなってしまうためです。
オブジェクト指向用語
クラス
- サブルーチン(関数)と変数をまとめる
- 全体の部品の数を減らせる
- 名前づけを楽にする
- クラスの内部だけで使う変数やサブルーチンを隠す
- 保守性を維持できる
- 1つのクラスからインスタンスをたくさん作る
- ファイル、文字列など、同種の情報を複数同時に扱う処理であっても、そのクラス内部のロジックをシンプルにできる
- 特定の関数からしかアクセスできない
- 関数実行中にだけ存在する
ポリモーフィズム
ポリモーフィズムは呼び出し側のロジックを一本化できる仕組み
- クラスライブラリに応用されている
RubyのGemはまさにライブラリそのものです。オブジェクトによって振る舞いは異なるものの、呼び出し側のロジック(メソッド)は同一です。
object.method
というような形式で呼び出せるパターンがほとんどではないでしょうか。継承
クラスの共通部分を別クラスにまとめる仕組み
- 共通に使いたいメソッドとインスタンス変数は共通クラス(スーパークラス)に定義し、利用したいクラス(サブクラス)はその共通することを宣言する
- 共通クラスを定義することで、コードの重複を排除できる
変数
インスタンス変数は、影響範囲を局所化できるローカル変数のメリットと、存在期間が長いグローバル変数のメリットの良いとこどりをした仕組み
- 別の関数からアクセスできないように隠すことができる
- 別の関数からアクセスできる
- インスタンス作成後は必要なくなるまでメモリ上に残される
- 複数作成できる
- どこからでも呼び出せる
- プログラムの最初から最後まで存在している
型
変数の型をあらかじめ決める仕組み
- コンパイラにメモリ領域の大きさを教えられる
- プログラムのエラーを防止できる
- プログラムのコンパイル時点でエラーを検出方式の言語が静的型付言語、プログラムの実行時点でエラーを検出する言語が動的型付言語
パッケージ
クラスをまとめる仕組み
Rubyにおいてパッケージとライブラリは同一視されており、どちらもGemを指す場合が多い。
例外
戻り値とは違う形式で、メソッドから特別なエラーを返す仕組み
ガーベジコレクション
インスタンス作成時に確保したメモリ領域を、インスタンス削除後に解放する仕組み
Rubyには
GC
というガーベジコレクションを制御するモジュールが組み込まれており、環境変数の設定変更ができる。プログラムの実行方式
- コンパイラ方式
- プログラムに書かれた命令をコンピューターが理解できる機械語に変換してから実行する
- コンパイルによって実行までに手間がかかるが、実行効率は良い
- インタプリンタ方式
- ソースコードに書かれたプログラムの命令をその場で逐次解釈しながら実行する
- 手軽に実行できるが、実行速度が遅い
- 中間コード方式
- コンパイラを使ってソースコードを中間コードに変換し、専用のインタプリンタによって解釈して実行する
- 実行の手間が少なく、実行効率も良い
- 中間コードを読み取ってCPUが理解できる機械語に変換する仕組みがVM(Virtual Machine)
スレッド
スレッドは、「プログラムの実行単位」で、1つのアプリケーションの中では異なる役割を持つ複数のスレッドが同時に並行して動いている
- CPUが複数のスレッドの処理を少しずつ順繰りに繰り返している(マルチスレッド環境)
オブジェクト指向言語におけるメモリの仕組み
オブジェクト指向のプログラムはメモリの使い方に特徴がある。そのため、メモリの仕組みを知っておくことで、メモリサイズが大きすぎたりするエラーに対処できるようになる
メモリには、静的領域とヒープ領域、スタック領域がああり、プログラムが実行されるにつれ、用途ごとに使い分けられている
静的領域
プログラムの開示しに確保され、以降プログラムが終了するまで配置が固定される領域
ヒープ領域
ヒープ領域はプログラムの実行時に動的に確保するためのメモリ領域
スタック領域
スタック領域 はこの前の節で説明したスレッドの制御のために使うメモリ領域
- ヒープ領域は複数のスレッドから共用されるが、このスタック領域はスレッドに1つずつ用意される
- 新しい情報がpushされ上に積み上がっていき、新しい情報からpopされ取り出されていくLIFO方式
1.クラスの生成
- クラス情報はクラスにつき1つだけ静的領域にロードされる
- 新しいクラスを使うコードを実行するたびに、クラスの情報を読み込んでメモリにロードする
- このタイミングでロード済みの他のクラス情報との関連づけを行う
2.インスタンス生成
- インスタンス生成のたびにヒープ領域が使われる
- インスタンスを作る命令(Javaではnew命令)を実行すると、そのクラスのインスタンス変数を格納するのに必要な大きさのメモリがヒープ領域に割り当てられる
- インスタンスとメソッドとの関連づけを行うため、静的領域にあるクラス情報との関連づけも行う
- インスタンスを変数に代入すると、変数にはヒープ領域のインスタンスのポインタが格納される
3.ローカル変数・引数
インスタンスメソッドにローカル変数や引数が含まれる場合はスタック領域に保存される
Rubyの場合、
Class.new
でクラスに対応するインスタンスを生成する。4.不要なインスタンス
- ヒープ領域に残った不要なインスタンスは、ガーベジコレクタによって自動的に削除される
- ガーベジコレクタはヒープ領域の状況を調べ、空きメモリ領域が少なくなったことを検知するとガーベジコレクション処理を実行する
- この処理は、スタックやメソッドエリアから参照されていない、孤立したインスタンスを探し出すことによって成立している
まとめ
今回は、『オブジェクト指向でなぜ作るか』を読んで、オブジェクト指向の用語とオブジェクト指向プログラミングのメモリの仕組みをまとめました。
オブジェクト指向用語を、Rubyに関連付けて理解することで、学習効率が高まり良かったです。
それでは!
コメントを残す