おはようございます、こんにちは、こんばんわ。
フリーランスの薬剤師として生活収入を得ながら、プログラミング言語を勉強している”Yuya Matsuura”と申します。
その中で、【WordPress】などにも採用されている≪PHP≫について、改めて学び始めておりまして、
ブログ記事としてアウトプットすることで知識の定着を狙う
+同じような境遇の方の参考になればと思い、シリーズ化して記事にさせて頂きます。
個人的な目標は”Raravel”(フレームワーク)をサクサク使いこなせるようになりたい!です。
※なお、追々記事でまとめるかは決めかねていますが、ローカル環境構築については今のところ記事にするつもりはないので、ご容赦ください。
アウトプット方式なので、記事としては見難いかも知れませんが、ご参考になれば幸いです。
今回から、個人的に初心者の【山場】であり、ただし避けては通れないオブジェクト指向・クラスについて数回にわたってまとめたく思います。
ご参考になれば幸いです。
オブジェクト・クラス・インスタンス・インスタンス化
「オブジェクト指向」、そして「クラス」というワードは、
PHPだけでなく、JAVAやJavaScriptなど様々なプログラミング言語で実装されている概念です。
色々なワードが新しく登場するので、なかなか理解するのが難しい概念かなと個人的に思っています。
まず見出しにある「オブジェクト」「クラス」「インスタンス」そして「インスタンス化」の4つのワードについて理解を進めましょう。
オブジェクト
PHPでの「オブジェクト」は、-変数や関数をひとまとめにしたもの- です。
関数もデータとして格納できる点で、「連想配列」とは異なります。
そして、さらにオブジェクトにおける変数の事を プロパティ
オブジェクトにおける関数の事を メソッド と呼びます。
新しいワードがたくさん出てきますが、もう覚えるしかないので覚えましょう!
なので、言い換えると「オブジェクトとは、プロパティとメソッドの集合体」とも言えます。
JavaScriptに出てくるとオブジェクトとほぼ同意義なので、まとめて学習したい方は下記の記事もご参考にしてください。
配列と連想配列(オブジェクト)を改めて整理しよう その2「オブジェクト」【基礎中の基礎⑧】【JavaScript】
ポイント① オブジェクトとは、プロパティ(変数)とメソッド(関数)をまとめたもの
そして、連想配列とは異なるので、記述方法も連想配列とは異なります。
連想配列はキーとプロパティを1つのセットとして、[ ] の中に ’キー’ => ‘プロパティ’ の形で格納します。
<?php
$deta = ['name' => 'Yamada', 'age' => 40, 'address' => 'Kyoto'];
?>
上の記述方法とは異なる形で、オブジェクトは記述します。
記述方法は、クラスやインスタンスの説明の際にまとめて例を出しますね。
ポイント② オブジェクトは、連想配列と記述方法が異なる
クラス
オブジェクト指向における「クラス」は、度々オブジェクトの設計図と例えられます。
同じような特徴(変数や関数)を持つオブジェクトを1個や2個だけでなく、例えば数100個規模で作成したいとします。
その度に、毎回同じようなコードを書くのは大変だと思いませんか?
そこで、クラスと言う概念が登場します。
あらかじめ使いまわしが出来る特徴はクラスとしてまとめておいて、記述しておきます。
そのクラス(設計図)を用いて、異なる部分だけ「のみ」変えてオブジェクトを作成すれば、コード量も減って楽になると思いませんか?
この辺りが納得いかない方のために、イメージ例です。
例えば、赤い車と、青い車と、黄色い車と、緑の車の4台を作りたいとしましょう。
この車はどれも、運転して公道を走ることが出来ます。
なので性能(特徴)としては、アクセルを踏めば加速するし、ブレーキを踏めば減速します。
また、右に曲がりたいときはウィンカーを出しますし、クラクションも付いています。
そういった共通の機能は関数(メソッド)としてまとめておくとしましょう。
そして異なる部分=車の色を「赤」「青」「黄色」「緑」の4色に変えればいいだけなので、
まとめておいたメソッドに関しては何回も記述する必要が無くなります。
事前にまとめられる情報は「クラス(設計図)」にまとめておいて、
クラス(設計図)からオブジェクト(モノ)をいざ作る際に異なる部分だけを変えて、作成します。
このような考えでコードを記述すること(リファクタリング)で、最終的に全体のコード量を減らすことが出来ますし、
また見やすくなったり、保守性が増したりもします。
このような記述方法が「オブジェクト指向」的な記述方法になります。
(ちょっと違うかもですが笑)
ポイント③ クラスは、オブジェクト作成における設計図の事
インスタンス、インスタンス化
上記で説明したようにクラス(設計図)からオブジェクト(モノ)を作成した時に、
特別のそのオブジェクトを「インスタンス」と呼んだりします。
英語だと「instance」で、意味的には実例・実数・実態みたいなニュアンスです。
新しいワードが出てきて、混乱するとは思いますが、
ここではクラスの概念におけるオブジェクトは「=インスタンス」と呼ぶ。で覚えておけばOKです。
またクラスからインスタンス(オブジェクト)を作る事を「インスタンス化」と言うので、合わせて覚えておきましょう。
ポイント④ インスタンスは、クラスから作られたオブジェクトと同義(で、一先ずOK)
実際にコード書いて、クラスからインスタンスを作ってみよう①(プロパティ格納)
クラスの作り方は下記のとおりです。
class クラス名 { }
ただし、クラス名は慣例的に大文字から書き始めます。
そして { } の中には共通で使いまわせるプロパティやメソッドを定義していきます。
実際に書いてみましょう。
<?php
class Member {
public $name;
}
$kimura = new Member();
$kimura->name = '木村';
echo $kimura->name;
?>
1つずつ説明していきます。
①クラスの作成(3~5行目)
class と言う宣言に続いて「クラス名」を記述します。
自由に付けることが出来ますが、今回は「Member」と言うクラス名にしました(慣例的に大文字から始める)。
{ }の中にプロパティやメソッドを記載していきますが、順を追いたいので、まずは「name」と言う変数を定義しました。
なお、まだ変数「name」には値は入っていません。
この際「$name」で変数を宣言する前に「public」と記述されていると思いますが、
この「public」はコード上必要なものと覚えておいてください。
(記述しないとエラーを起こします)
「public」と「private」の違い、使い分け
「public」:クラス内でもクラス外でも、どこからでもアクセス可能
「private」:クラス外からのアクセス不可
コードを下に進むと、9行目で「name」に値を代入していますが、
「private $name」に場合はエラーを起こします。
なぜなら、クラスの外からアクセスしようとしているからです。
この記述例では「public」を用いる必要性があります。
ただし、基本的に保守性の関係から(制限をかけた方が安全性がUP)、基本は「private」で記述し、
必要に応じて「public」に書き換えてその範囲を広げるようにするのがベターかと思われます。
②インスタンス化により、インスタンスを作成(7行目)
インスタンスは new クラス名() と記述することで作成することが出来ます。
()は必須になりますので忘れないようにしましょう!
(後のコンストラクタ関数の説明で、その必要性が分かるかと思います。)
そして、 new クラス名() で作成したインスタンスを、変数「$kimura」に格納しました。
③インスタンスの中身を取り出す(9行目)
作成したインスタンスはクラス(設計図)の情報を引きついているので、
もちろんプロパティ「name」が定義されています。
ただし、この時点では「name」に値が入っていないので、’木村’と言う文字列を代入したいと思います。
プロパティ「name」を呼び出すには、インスタンスを格納した変数に続いて
->「プロパティ」
と記載します。
今回例では、$kimura->name でプロパティ「name」を呼び出すことが出来ました。
(なお、nameの前には「$」不要。むしろ記載するとエラー。ややこしい)
更に = ‘木村’; と記載して、値(文字列)を代入してあげます。
④最後にエコー文で確認(11行目)
echo文で正しくブラウザに「木村」と表示されているか確認して見ましょう!
なお、この際もインスタンスの中のプロパティ「name」を呼び出すので、
=>nameの書き方でechoしています。
実際にコード書いて、クラスからインスタンスを作ってみよう②(メソッド格納)
上記例では、クラスの中に「name」と言うプロパティを定義しました。
同じ考えでメソッド(関数)も書いていきましょう。
個人的にはここが最悩みポイントです。
<?php
class Member {
private $name;
public function get_name(string $name) {
$this->name = $name;
echo $this->name;
}
}
$kimura = new Member();
$kimura->get_name('木村');
?>
ブラウザへの出力結果は同じく「木村」となります。
先のプロパティと異なる部分を中心に解説します。
①private(public) に続けて関数を宣言する (6行目)
4行目で定義したプロパティ「name」を用いてメソッドを定義していきます。
まず「name」の変数に「private」を使用しています。
これは、この先に定義するメソッドも同一のクラス内で宣言し「name」を使用していくため、
同一のクラス内という事で保守性が高い「private」が使用できます。
(もちろん「public」でもエラーは生じませんが、変えれる部分は「private」で宣言しましょう)
メソッド(関数)も「public」または「private」を先に記述し、後にfunction 関数名() と続けます。
もちろん関数名の後の () には引数を渡せるので、今回は4行目で定義した「name」を関数内に渡していきましょう。
ちなみに () 内の引数の$nameの前に「string」と記載してますが、これは型宣言です。
string(文字列)を変数の前に宣言して、より保守性の高い記述としています。
型宣言の参考記事は↓↓です。
【バックエンド初心者がまとめるPHP学習日記⑦】PHPにおける型の概念
ちなみにメソッド「get_name」(もちろん関数名は自由)の先頭には「public」を記述しています。
ここを「public」にすることで、クラス外でもメソッドを使うことが出来ますし、
引数として渡している「$name」もクラス外で引数として値を代入することが出来ます。
実際に書いてみると分かると思いますので、一先ず先に進みましょう。
②「$this」を用いてプロパティにアクセスする(7行目)
$this->name = $name;
メソッド内の{ }内に記述した上記の1行ですが、個人的にここが最大に悩んだ部分でありますので、
同じくクラスについて学び始めの方の参考になれば良いなと思いながら、解説させて頂きます。
まず「=」で挟んだ左右の各々の「name」ですが、実は全く違う物です。
先に右辺の「$name」ですが、これは6行目の関数名(引数)から渡ってきた「name」です。
なので、最終的にget_name()関数を呼び出す際に()内に引数を記述して、渡していく訳ですので、
get_name(‘稲垣’)と記述すれば、「’稲垣’」が6行目の()内に入って、7行目以降に渡っていきます。
渡っていく先が右辺の「$name」になります。
続いて、左辺の「name」は何を指すのかを説明するには、まず「this」についての知識が必要ですが、
ここのメソッド内で記述している「$this」は -このインスタンス- そのものに該当します。
クラスは「new」を使い、この後インスタンス化しますので、
ここで言う「$this」は作成したインスタンスそのものを指す訳です。
それでは左辺の「$this->name」を見ていきますが、
$thisはインスタンスそのものを指すと言いましたので、最終的には今回で言うと「$kimura」とイコールになります。
そこから -> nameでプロパティを取得していきますので、結果的には「$kimura->name」と同義になりますね。
という事で左辺のnameは4行目で記述したプロパティ名になります。
分かり難いと思いますが、左辺の「name」はプロパティ、
右辺の「name」は変数になり、関数を実行するとき渡ってくる値になりますので、
結果的に関数を宣言した際の()内の値(引数)がインスタンスのプロパティの値に入ります。
・・・ややこしい!
③関数内にecho文を追記、関数の実行(8行目、14行目)
echo文も一緒に関数内に定義しました(8行目)。
メソッド内なので $this-> でプロパティ「name」を呼び出します。
その後は上記プロパティ呼び出し例と同じ記述です。
newで新しくインスタンスを生成して、変数に格納します。
定義した変数から、->get_name()でメソッドを呼び出しましょう。
( )に記述する値がブラウザに表示されれば問題無くコードが作動しております!
まとめ
以上がクラスの基本的な考え方と記述方法です。
新しいワードがたくさん出てきて混乱する方もいるのではないでしょうか?(自分です)
次回は、もう少しクラスに対しての記述方法を深掘りしてみようと思います。
また次の記事でお会いしましょう!
コメント