はじめに
未経験からweb系エンジニアになり今年で3年目。
プログラミングに興味を持ち勉強していた時から、
ネットで「オブジェクト指向」についての記事や、
スクールに通っていた時のメンターさんや友人から
「オブジェクト指向」が大事と、何度も耳にしてきたけど
果たしてその理解は当時からどれぐらい深まっているのか気になり、
この記事を書くことにしました。
オブジェクト指向の3大要素
まずオブジェクト指向には3つの大きな要素がある
それが、継承と、ポリモーフィズムと、カプセル化
継承
継承は親クラスから機能を受け継ぐということ。
そのため、継承はクラス同士の関係が「AはBである」と表現できる時に
クラスを抽象的にまとめられるものということになります。
「パトカーは自動車である」
「救急車は自動車である」
「トラックは自動車である」はOK。
「自動車はパトカーである」はNG。
以外と簡単そうに感じましたが
コードを書くことに夢中になっていると
他のクラスの機能を使いたいがために安易に継承してしまったり、
気が付いたらこの「AはBである」という原則を破ってしまうことがあるので注意が必要。
例)jp環境でよく見る継承
r2/admin/lib/common_def.php
class MV {
// 中身省略
}
各ファイル
// MVクラスを継承
class UserMV extends MV {
function model() {
// 中身省略
}
function view() {
// 中身省略
}
}
ポリモーフィズム
これが一番ピンとこなかった要素でしたが、
重要な考え方となるポリモーフィズムとは、
同じメソッドの呼び出しであっても、オブジェクトが変われば振る舞いが変わることを言うらしい。
例えば、下記のような
2つの関数(perfomeとecho_log)があった場合、
ログの出力方法が標準出力になっていますが、
これをファイルにログを残したいという仕様変更がある場合どうすればでしょうか。
echo_logメソッドを直接書き換える必要が出てきてしまいます。
そうすると、
元のプログラムに修正を入れる必要があるため、修正が困難になってしまいます。
<?php
function perfome()
{
echo_log('peform');
}
function echo_log($message)
{
echo $message;
}
perfome();
じゃあ、ここにオブジェクト指向を導入するとどうなるか。
<?php
function perfome($logger)
{
$logger->log('やっほー');
}
class EchoLogger
{
public function log($message)
{
echo $message;
}
}
class FileLogger
{
protected $fileWriter;
public function log($message)
{
//エラーログをon
ini_set('log_errors', 'On');
//エラーログの記録先を指定
ini_set('error_log', '/Users/Shiga1/git/skill_up_training/error.log');
//エラーログに記録
error_log($message);
}
}
$object = new EchoLogger;
// $object = new FileLogger;
perfome($object);
perfome 関数は引数に
$logger オブジェクトを受け取り、そのlogメソッドを呼ぶ形に変わっています。
さっきの例との違いは
ログの出力を標準出力からファイル出力に変更したい場合、
元のコードの echo_log 関数を直接編集する必要がありました。
ですが、今回の例では
perfome 関数は、引数で受け取った$loggerオブジェクトのlogというメソッドを呼び出しているだけです。
つまり、ログの出力方法を変更したい場合、
元のコードは修正することなく、
perfome関数に渡していたオブジェクトを EchoLogger オブジェクトから FileLogger に変更するだけで良いことになります。
これが、
「同じメソッドの呼び出しであってもオブジェクトが変われば振る舞いが変わる」
というポリモーフィズム(多様性)です。
カプセル化
カプセル化は、
複雑な部分を隠して使う人はその複雑な中身を知らなくても良いこと。
日常生活で例えて分かりやすかったのが車。
アクセルを踏む。と車は加速して前に進みます。
当たり前のように思えますが、
実際、内部的にはアクセルを踏むことで、、、
様々な部品(ワイヤー、バルブ、エンジン、タイヤ、車体など)が内部でいろんなことをやって
結果的に前に進んでいます。
このように実際には利用する参照先(車)が内部でやってる複雑な事を隠して、
アクセルを踏む。
という行為だけを参照元(運転手)に公開して、
運転手は「アクセルを踏めば加速する」という事だけ知ってれば良い。
という状態にすることがカプセル化だと思ってます。
まとめ
未経験の頃からよく目にしたり耳にしたりしてる「オブジェクト指向」について
今回改めて調べてみて、あれから自分の理解がどれぐらい深まったか?という点でも
記事にしてみて良かったなと思いました。
実際のところ、
ポリモーフィズムについては
記事の書き出しではほぼ理解できていなかったです。
また、他の継承や、カプセル化についても
調べるともっと深く考えたりしている記事なんかもあったりして
まだまだ表面上の理解だなーとも思いましたし、
phpのweb系エンジニアでやっていくなら、
この辺の理解は必須なので、
また定期的に今回参考にさせてもらった記事など読んで、
自分の理解度が上がったか確かめに来たいなと思いました。
参考
オブジェクト指向と10年戦ってわかったこと
https://qiita.com/tutinoco/items/6952b01e5fc38914ec4e
PHPで学ぶオブジェクト指向
https://qiita.com/ritukiii/items/a1979c3bcdcea9454d53