20210501・2・3_アウトプット(オブジェクト指向・PHP)
行ったこと
5/1
- オブジェクト指向でなぜつくるのか(パッケージ・例外・ガベージコレクション・メモリの使われ方)
5/2
5/3
学んだこと
パッケージ・例外・ガベージコレクションについて
「オブジェクト指向」について、基本的なクラス・ポリモーフィズム・継承の他にオブジェクト指向型言語には便利な仕組みが3つある。
パッケージとは?
クラスをくくることができる仕組み。パソコンにある「フォルダ」のようなイメージ。「ただの入れ物」なので、パッケージに対してインスタンス変数やメソッドを作成することはできない。
パッケージのおかげで名前空間(同じクラス名であっても影響を与えない)ができるよ。
例外とは?
予期せぬ状況が起きたときに、「ここでエラーが出ているよ、助けて」と戻り値とは違う形式で返す仕組み。
A→B→Cという処理(サブルーチン)があった時に、今まではそれぞれにエラーが起きたときの処理を書いていて、重複していた。(冗長)また、そもそもの処理の書き間違えをすると、エラーを吐き出すことができない恐れもあった。
その問題を解決するために、上記の例で言うと、Cでエラーが起きたら、Bは「Cで起きているよ(詳しくはCを見て)」と宣言するだけにしたり、例外を宣言しているメソッド側において、例外を処理するロジックを書かないと(エラーを発生させる側・エラーを受け取る側が噛み合っていないと)プログラムをエラーにさせるようになった。
ガベージコレクションとは?
インスタンスのゴミを自動で集めて削除する仕組み。今までは、プログラムを作成するときに、どのようにメモリを解放するか・解放の処理も手作業で行っていた。それらを、プログラム言語側の処理として行ってくれる機能。
メモリの使われ方
一時的にメモリを保存しておくところとして「静的領域」「スタック領域」「ヒープ領域」の大きく3つある。
領域 | 内容 |
---|---|
静的領域 | アプリの開始〜終了まで変わらないメモリ領域。グローバル変数やクラス情報など。(プログラムの実行時に変化しないから「静的」だよ!) |
スタック領域 | スレッドごと(プロセスよりも小さな単位)に作られるメモリ領域。ローカル変数・関数の引数・戻り値など。効率よくするために、「後入れ先だし」なことがポイント。 |
ヒープ領域 | 動的なもののために作られるメモリ領域。インスタンスが作られるたびにここが使われるよ!(OSや仮想マシンが割り当て・解放処理を管理してくれるよ) |
ポイントとしては、
- 前述したガベージコレクションは、「静的領域」と「スタック領域」と手を繋いでいないメモリを「ゴミくず」と判断して、削除していること。(つまり、その2領域から無駄に参照されていると残り続けてしまう)
- クラス情報は、インスタンス変数を生成する前に、一度読み込まれる(全てのクラス情報を一気に読み込むか、必要な時に逐次読み込むかは言語仕様によるが、JavaやPHPは後者)
- インスタンス変数は、
new
をした時にインスタンス自体は「ヒープ領域」を使用するが、参照元などの「インスタンス変数」自体は、ポインタ(住所)のみ対象エリアに格納される。(インスタンス変数の中身によって「静的領域」あるいは「スタック領域」へ。) - ポインタで格納するメリットは、内容の大きさに関わらず常に同じ形式でインスタンスを管理することができるため。(例えば、北海道に住んでいても東京に住んでいても(実際に住んでいる土地の大きさは違うけれど)「住所」で表現した時には葉書一枚に収まるという意味)
- 上記らのことを踏まえてインスタンスのメモリが使われる時の注意点としては、メモリの一時保存先が異なることから、作ったインスタンスの数と、それに納める内容の数が一致していないと、納め先がなくなり、意図しない代入(入れるところないから上書きしよう)とわかりづらいバグを起こすことがあるよ!
PHPの配列・関数について
配列について
- Rubyで言うと「ハッシュ」のことを「連想配列」と言う。
- Rubyで言うと「配列」のことを「数値配列」と言う。
- 配列を
[ 配列内容];
で表現できるようになったのはPHP5.4からなんだって!(それまではarray(内容);
で表現) foreach
について、要素の中身を変更するには、$key変数を配列のインデックスとして使い、要素の中身を変更した後、その内容を表示するにはもう一度foreach
をする。(「$key変数を配列のインデックスとして使う」というのは、例として、foreach($meals) as $dish => $price { 内容〜
でキーを$dishとして設定した後、$meals[$dish] = $meals[$dish] * 2;
のようにキーに対して2倍の処理と代入すると、値を変更できるという意味)
覚えた単語 | 意味 |
---|---|
in_array | 要素から値を探してtrueかfalseで返す |
array_key_exists | 要素からキーを探してtrueかfalseで返す |
array_serach | 要素から値を探してキーを返す(ホテルの受付のイメージで覚えた!「この部屋を予約しているんですが」「はい、鍵です」のイメージ) |
unset | (キーと値を指定して)対象の要素を消す |
array_reverse | 配列の中身を逆順にする |
array_splice | 対象の値を削除して置き換える |
explode | 文字列を配列にする |
implode | 配列を文字列にする |
sort | 並び替え(数値配列で使う) |
asort | 値で並び替え |
ksort | キーで並べ替え |
関数について(ユーザー定義関数のところまで)
function 関数名(引数) { 内容 }
で定義して、関数名(引数);
で呼び出す。- 引数の数が合わないとエラーが出ることはRubyと同じ。
- Rubyと同じようにデフォルト値を設定することができる。デフォルト値に設定できるのはリテラル(数値や文字列を直接書いたもの)のみ。(変数に変数を定義はできない❌)設定する際は、引数として必須のものを引数内の前半に書き、デフォルト値を設定するような任意のものは後半に書く。
感想
- オブジェクト指向の本のおかげで、背景知識が深まり、配列や関数を学んでいるときにちょっとしたこと(例えば本の中で「引数の名前が関数外の変数を同じ名前の場合に引数を変更しても関数外でも変数に影響を与えない」と言う文章が出てきたときに「ああ、この背景としてメモリの使われ方が違うからだ」と感じるようになったこと)が嬉しかった。
- 実際にコードを書いているとついセミコロンを忘れる😅
- つい、理解が遅いのでは?と焦ってしまう自分がいるが、着実に理解はしていると励まして進めようと思う。