近年のプログラミング言語は、すべてオブジェクト指向になっています。
当初は、手続き型の言語も、バージョンアップを重ねるごとに、オブジェクト指向へと変わってきました。
したがって、オブジェクト指向を理解していなければ、どの言語も理解が難しいということになります。
とは言っても、最近は、無理やりクラスを多用し、「自分はオブジェクト指向を理解しています」を強調しているような気もします。
オブジェクトは、必要な時に、必要な個所で使用することで、威力を発揮します。
ここでは、クラスと、理想的なオブジェクト指向を学習します。
- オブジェクトとは
私たちは、木でできた彫刻をオブジェと呼びますが、山に生えている木を、オブジェとは呼びませんね。 彫刻は、木に、人間のアイデアや技術が加わって初めてオブジェになります。 プログラミングで言うオブジェクトも、これと同じです。 プロパティやメソッドなど、いろいろな要素が組み合わさって出来ている「物体」がオブジェクトです。
- クラス(class)とは
クラスは、「ひな形」テンプレートです。 パソコンで年賀状を書こうとするとき、テンプレートを使用しますね。 このテンプレートが、クラスそのものです。
年賀状クラスには、宛先を書く領域や、宛名を書く領域、差出人を書く領域が用意されているだけで、実際には書かれてはいませんので、送ることは出来ません。
このクラスに、宛先や、宛名、差出人のデータをセットして、送信メソッドで送信するのがオブジェクトです。
- クラスからオブジェクト
class 年賀状 { public $宛先 = ""; public $宛名 = ""; public $差出人 = ""; public function send_nenga() { ポスト投函 } }
このような、年賀状classが有ります。
- 年賀状は、郵便局に売られているクラスです。買ってきた年賀状は、インスタンスにして、オブジェクトになります。
$nenga1 = new 年賀状(); - 年賀状にプロパティをセットします。
$nenga1->宛先 = "東京都千代田区神田1-10";
$nenga1->宛名 = "オブジェ 太郎";
$nenga1->差出人 = "クラス 花子"; - メソッド、send_nengaを呼び出して、年賀状を送ります。
$nenga1->send_nenga();
いかがですか、ご理解いただけましたか。
- 年賀状は、郵便局に売られているクラスです。買ってきた年賀状は、インスタンスにして、オブジェクトになります。
- コンストラクタを追加
コンストラクタは、クラスからオブジェクトを作成したとき、一度だけ実行される、特殊なメソッドです。 public function __construct() のように、アンダーバー(アンダースコアとも言う、古い人間なのでアンダーバーで統一)2個から始まる関数名になっています。class 年賀状 { public $宛先 = ""; public $宛名 = ""; public $差出人 = ""; public function __construct($宛先, $宛名, $差出人) { $this->宛先 = $宛先; $this->宛名 = $宛名; $this->差出人 = $差出人; } public function send_nenga() { ポスト投函 } }
オブジェクトの作成時に、コンストラクタに値を渡すことで、1度にプロパティをセットすることができます。
$nenga1 = new 年賀状("東京都千代田区神田1-10", "オブジェ 太郎", "クラス 花子");
$nenga1->send_nenga();
5行が、2行になりましたので、ずいぶん奇麗に見えます。
- 実例で見てみましょう
それでは、年賀状の発送を、メールの送信に置き換えて見てみましょう。## メール送信クラス class SMTP { public $subject = ""; public $to = ""; public $from = ""; public $body = ""; public function __construct($subject='',$from='',$to='',$body='') { $subject && $this->subject = $subject; $from && $this->from = $from; $to && $this->to = $to; $body && $this->body = $body; } public function send_email() { mb_language("Japanese"); mb_internal_encoding("UTF-8"); $headers = join("\n", array( "MIME-Version: 1.0", "X-Sender: ". $_SERVER['SERVER_NAME'], "X-Mailer: PHP/". phpversion(), "Message-Id: <" . md5(uniqid(microtime())) . ">", "From: ". $this->from, "Reply-To: ". $this->from, "Return-Path: ". $this->from. "\n" "Content-Type: text/plain; charset=\"UTF-8\"\n\n"; )); return(mail( $this->to, $this->subject, $Body .= $this->body ."\n\n", $headers, "-f". $this->from )); } }
これは、実際のLinuxインターネットサーバからメールを送信するクラスです。(一部省略)
複雑に見えるかもしれませんが、ほとんど年賀状と同じです。 プロパティは、$subject(メールのタイトル)、$to(送信先Email)、$from(送信元Email)、$body(メール本文)で、 メソッド、send_emailを呼び出して送信します。
$email = new SMTP("先日のお礼", "jibun@google.com", "anata@yahoo.co.jp", "先日はありがとうございました。今後共よろしくお願いいたします。");
$email->send_email();
クラスのコンストラクタの引数に順に、値を渡してオブジェクトを生成し、send_email()メソッドで送信しています。 いかがでしょうか、年賀状とまったく同じ処理をしていますね。メール送信の完全なクラスは、別途クラスライブラリで公開します。 完全版は、CC、BCC、文字化け対策にも対応、html形式、添付ファイルも送信できます。
- 継承
ここに2つの年賀状があります。
内容は、ほとんど同じで、違っているのは裏のデザインだけです。 これをクラスにしようとすると、ほとんど同じことを二度書かなければならなくなります。 それなら、同じ部分を1つの親クラスにして、その複写に、違った部分だけを追加した、子クラスを作成すれば、同じことを書かなくてよくなります。 これが継承です。class 親年賀状 { public $宛先 = ""; public $宛名 = ""; public $差出人 = ""; public function __construct($宛先, $宛名, $差出人) { $this->宛先 = $宛先; $this->宛名 = $宛名; $this->差出人 = $差出人; } public function send_nenga() { ポスト投函 } } class 子年賀状1 extends 親年賀状 { public $裏 = "画像1"; public function __construct() { parent::__construct(); } } class 子年賀状2 extends 親年賀状 { public $裏 = "画像2"; public function __construct() { parent::__construct(); } }
いかがでしょうか、これで仕事用と、一般用のクラスができました。同じコードは、ほとんど記述されていません。 子クラスは、extendsキーワードの後ろに親クラスを指定して継承します。 あとは、異なる裏のデザインを指定しているだけです。子クラスは、親クラスのコンストラクタを、自動的には実行しませんので、 子クラスのコンストラクタから、親クラスのコンストラクタをparent::__construct();で呼び出しています。 2つだと、たいしたコード量ではありませんが、3つ、4つとなれば違ってきます。 何より、それぞれの年賀状に、「郵便番号プロパティ」を追加したいとなった時、個々に作成していれば、すべてのクラスを変更しなくてはならず、 手間が大きくなるだけでなく、不具合の原因ともなります。継承していれば、親クラスを変更するだけで完了です。
ただ、こんな単純なクラスなら、継承で複数のクラスを作成するより、わたしならプロパティで、裏デザインを変更するか、 メソッドで変更しますね。継承するプロパティが多く、変更する箇所も多い場合に重宝しますので、継承が有ることだけを覚えておけば結構です。
お一人で開発している場合や、小さいシステム、二度と作成することのない案件を、無理やりオブジェクトにして、余計に分かりにくいコードにする必要はありません。 関数で可能なものは関数で、使いまわす必要が有る場合や、複数人で開発される場合は、オブジェクト指向は有効です。