構造化とオブジェクト指向 (5/7)
作成:2010-12-11 21:18
更新:2010-12-11 21:23
更新:2010-12-11 21:23
■継承による機能拡張
オブジェクト指向では、作成したクラスはあちこちで再利用することができます。が、実際に利用しようとすると、「ここをこう手直しした使いたい」とか「これは機能的にいまいちだからもっと強化したい」ということも出てくるでしょう。
こうしたとき、クラスのコードを書き換えて……というのも一つの方法ですが、もし大きなプロジェクトで大勢が開発に携わっていたりすると、勝手にクラスの中身を書き換えたおかげでそこらじゅうで悲鳴が上がる……なんてことになりかねません。といって、クラスのコードをコピーしてまた新しいクラスを作る……というのも馬鹿げています。ほとんど同じで、一部だけちょっと違うクラスをいくつも作るのはコードの無駄です。
もとのクラスはいじらない。そして最低限の修正だけでクラスを再利用出来るようにする。そういう考えのもとに生み出されたのが「継承」という概念です。
継承とは、既にあるクラスの機能をそのまますべて受け継いで新しいクラスを作ることです。これは、以下のようにしてクラスを定義することで使えるようになります。
下に、先程のサンプルを更に修正したものを挙げておきましょう。ここでは、TextModifyクラスを継承して、「TitleModify」「MsgModify」「RepModify」といったサブクラスを作りました。これらでは、それぞれ__constructを用意し、そこで必要な設定を行うようにしてあります。
これらのサブクラスにはコンストラクタしかありませんが、その中では各フィールドの値をアクセサ・メソッドで設定していますし、実際の利用シーンではwriteRenderTextで出力をしています。スーパークラスTextModifyにある機能がそのまま使えることがわかるでしょう。
このようにして、クラスを更に継承して機能強化し、再利用することで、より柔軟にクラス作成が行えるようになるのです。
こうしたとき、クラスのコードを書き換えて……というのも一つの方法ですが、もし大きなプロジェクトで大勢が開発に携わっていたりすると、勝手にクラスの中身を書き換えたおかげでそこらじゅうで悲鳴が上がる……なんてことになりかねません。といって、クラスのコードをコピーしてまた新しいクラスを作る……というのも馬鹿げています。ほとんど同じで、一部だけちょっと違うクラスをいくつも作るのはコードの無駄です。
もとのクラスはいじらない。そして最低限の修正だけでクラスを再利用出来るようにする。そういう考えのもとに生み出されたのが「継承」という概念です。
継承とは、既にあるクラスの機能をそのまますべて受け継いで新しいクラスを作ることです。これは、以下のようにしてクラスを定義することで使えるようになります。
class クラス名 extends 継承するクラス {……}この継承するもとになるクラスを「スーパークラス」、継承して新たに作ったクラスを「サブクラス」といいます。サブクラスでは、スーパークラスにあるすべてのフィールド、メソッドを受け継ぎ、そのまま使うことができます(ただし、アクセス・キーワードでprivateにされたものは隠蔽されているので使えません)。
下に、先程のサンプルを更に修正したものを挙げておきましょう。ここでは、TextModifyクラスを継承して、「TitleModify」「MsgModify」「RepModify」といったサブクラスを作りました。これらでは、それぞれ__constructを用意し、そこで必要な設定を行うようにしてあります。
これらのサブクラスにはコンストラクタしかありませんが、その中では各フィールドの値をアクセサ・メソッドで設定していますし、実際の利用シーンではwriteRenderTextで出力をしています。スーパークラスTextModifyにある機能がそのまま使えることがわかるでしょう。
このようにして、クラスを更に継承して機能強化し、再利用することで、より柔軟にクラス作成が行えるようになるのです。
(by. SYODA-Tuyano.)
※プログラムリストが表示されない場合
AddBlockなどの広告ブロックツールがONになっていると、プログラムリスト等が表示されない場合があります。これらのツールをOFFにしてみてください。
●プログラム・リスト●
<?php class TextModify { private $header = "<b>"; private $footer = "</b>"; private $body = ""; private $find = "PHP"; public function __construct($h,$f){ $this->setHeader($h); $this->setFooter($f); } function setHeader($s){ $this->header = $s; } function setFooter($s){ $this->footer = $s; } function setBody($s){ $this->body = htmlspecialchars(strtoupper($s)); } function setFind($s){ $this->find = $s; } function getRenderText(){ $res = str_replace($this->find, $this->header . $this->find . $this->footer, $this->body); return $res; } function writeRenderText(){ echo $this->getRenderText(); } } class TitleModify extends TextModify { public function __construct($s){ $this->setHeader('<span style="color:red;">'); $this->setFooter('</span>'); $this->setFind('PHP'); $this->setBody($s); } } class MsgModify extends TextModify { public function __construct($s){ $this->setHeader('<span style="color:blue;">'); $this->setFooter('</span>'); $this->setFind('PHP'); $this->setBody($s); } } class RepModify extends TextModify { public function __construct($s){ $this->setHeader('<b>'); $this->setFooter('</b>'); $this->setFind('PHP'); $this->setBody($s); } } // インスタンスの準備 $title_obj = new TitleModify('Hello PHP!'); $msg_obj = new MsgModify('ここに、PHPという文字を含む文章を書いて下さい。'); if ($_POST != null){ $str = $_POST['text1']; $rep_obj = new RepModify($str); } ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>sample page</title> </head> <body> <h1><?php $title_obj->writeRenderText(); ?></h1> <p><?php $msg_obj->writeRenderText(); ?></p> <hr> <p><?php if (isset($rep_obj)) $rep_obj->writeRenderText(); ?></p> <form method="post" action="./index.php"> <textarea name="text1" cols="40" rows="5"><?php echo $str; ?></textarea> <br><input type="submit"> </form> <hr> </body> </html>
※関連コンテンツ