Contents
PHPオブジェクト指向
すでにオブジェクト指向がわかるかたもわからない方も勉強していきましょう。
オブジェクト指向とは?
いろいろなものにたとえられる「たい焼きの型」とか「箱」やらそれぞれわかりやすかんがえでいいと思います。
例
わかりやすい考え ゲームにたとえますか、、、、車種が100台あるゲームがあるとしてそれをプログラムしていきましょう
car no1車はAボタンを押すと走る。Bボタンを押すと止まる
car no2車はAボタンを押すと走る。Bボタンを押すと止まる
car no3車はAボタンを押すと走る。Bボタンを押すと止まる
100台プログラミングするには大変ですね。
なのでここでは100台の車を「車」というオブジェクト(物)として考えましょう
じゃ、どうする?
「車」というモノを先に作っておいて、
Aボタンを押すと動く。Bボタンを押すと止まるよう
car no1車は「車」をコピーして外装の色だけ赤にする
car no2車は「車」をコピーして外装の色だけ青にする
car no3車は「車」をコピーして外装の色だけ緑にする
こんな感じなららくじゃね?ってことです。HTMLにたいしてのCSSもそうですね。
こんな感じをイメージしてください。
ではまたこっから難しめな説明をしていきます。
オブジェクト指向はどんなのがある?
以下みてください
- クラス - クラスは、同じ種類(またはクラス)のオブジェクトの多くのインスタンスを作成するためのテンプレートと考えることができます。車ね。
- オブジェクト – クラスによって定義されたデータ構造の個々のインスタンス。一度クラスを定義してから、そのクラスに属する多くのオブジェクトを作成します。オブジェクトはインスタンスとも呼ばれます。車種ね。
- メンバー変数 – これはクラス内で定義された変数です。このデータは、クラスの外部には見えなくなり、メンバ関数を介してアクセスすることができます。
- メンバー関数 – クラス内で定義された関数で、オブジェクトデータにアクセスするために使用されます。
- 継承 – クラスが親クラスの既存の関数を継承して定義されている場合、継承と呼ばれます。ここで、子クラスは親クラスのメンバー関数と変数のすべてまたは少数を継承します。車のいいところをとってトラクターにするとかね。
- 親クラス – 別のクラスから継承したクラス。これは基本クラスまたはスーパークラスとも呼ばれます。
- 子クラス – 別のクラスから継承するクラス。これは、サブクラスまたは派生クラスとも呼ばれます。
- ポリモーフィズム – これはオブジェクト指向のコンセプトで、同じ機能をさまざまな目的に使用できます。たとえばプログラマと土建屋さんではおなじ「業務」でも違うことをおこなってますよね?「業務」というものでも、パソコンたたくのと釘たたくのではちがうわけですよ。
- オーバーロード – オペレータの一部またはすべてが引数の型によって異なる実装を持つ多型の一種。同様に、異なる実装で関数をオーバーロードすることもできます。例えば、会員登録を行う機能で、名前と国名を登録させたいとします。国名を入力しなかった会員は国名:日本で登録します。
この場合、toroku、torokuJAPANというように別のメソッド名を付けるのではなく、おなじ登録機能があるため、同じメソッド名としたい場合があります
- その際、toroku(String name,String country)、toroku(String name)というように同じ名前のメソッドを引数の数を変えて作成する。
- データ抽象化 – 実装の詳細が非表示(抽象化)されているデータの表現。
- カプセル化 – すべてのデータとメンバー関数をまとめてオブジェクトを形成するコンセプトを指します。
- コンストラクター(Constructor) – クラスからオブジェクトが形成されるたびに自動的に呼び出される特殊なタイプの関数を指します。
- デストラクタ – オブジェクトが削除されるかスコープ外に出るたびに自動的に呼び出される特殊なタイプの関数を指します。
PHPクラスの定義
PHPで新しいクラスを定義する一般的な形式は次のとおりです –
<?php class phpClass { var $var1; var $var2 = "constant string"; function myfunc ($arg1, $arg2) { [..] } [..] } ?>
ここに各行の説明があります –
- 特別なフォームクラス、続いて定義するクラスの名前。
- 任意の数の変数宣言と関数定義を囲む中カッコの集合。
- 変数の宣言は特殊な形式varで始まり、従来の$変数名が続きます。彼らはまた、一定の値への最初の割り当てを持つかもしれません。
- 関数定義はスタンドアロンのPHP関数によく似ていますが、クラスに対してローカルであり、オブジェクトデータの設定やアクセスに使用されます。
例
本の種類のクラスを定義する例 –
<?php class Books { /* Member variables */ var $price; var $title; /* Member functions */ function setPrice($par){ $this->price = $par; } function getPrice(){ echo $this->price ."<br/>"; } function setTitle($par){ $this->title = $par; } function getTitle(){ echo $this->title ." <br/>"; } } ?>
変数$ thisは特別な変数であり、同じオブジェクトを参照しています。自体。
PHPでのオブジェクトの作成
クラスを定義したら、そのクラス・タイプの好きなだけ多くのオブジェクトを作成できます。以下は、new演算子を使ってオブジェクトを作成する方法の例です。
$physics = new Books; $maths = new Books; $chemistry = new Books;
ここでは3つのオブジェクトを作成し、これらのオブジェクトは互いに独立しており、それらのオブジェクトは別々に存在します。次に、メンバー関数とプロセスメンバー変数にアクセスする方法を見ていきます。
メンバー関数の呼び出し
オブジェクトを作成すると、そのオブジェクトに関連するメンバー関数を呼び出すことができます。1つのメンバ関数は、関連オブジェクトのメンバ変数のみを処理することができます。
次の例は、メンバー関数を呼び出して3冊の書籍のタイトルと価格を設定する方法を示しています。
$physics->setTitle( "Physics for High School" ); $chemistry->setTitle( "Advanced Chemistry" ); $maths->setTitle( "Algebra" ); $physics->setPrice( 10 ); $chemistry->setPrice( 15 ); $maths->setPrice( 7 );
今度は、上記の例で設定した値を取得するために別のメンバ関数を呼び出します。
$physics->getTitle(); $chemistry->getTitle(); $maths->getTitle(); $physics->getPrice(); $chemistry->getPrice(); $maths->getPrice();
これにより、次の結果が生成されます。
Physics for High School Advanced Chemistry Algebra 10 15 7
コンストラクタ関数
コンストラクター関数は、オブジェクトが作成されるたびに自動的に呼び出される特別なタイプの関数です。そこで、コンストラクタ関数を通して多くのことを初期化することによって、この振る舞いを最大限に活用します。
PHPはコンストラクタを定義するために__construct()という特殊な関数を提供しています。好きな引数をコンストラクタ関数に渡すことができます。
次の例では、Booksクラスのコンストラクタを1つ作成し、オブジェクト作成時に書籍の価格とタイトルを初期化します。
function __construct( $par1, $par2 ) { $this->title = $par1; $this->price = $par2; }
これで、set関数を別々に呼び出して価格とタイトルを設定する必要はありません。この2つのメンバ変数は、オブジェクト作成時にのみ初期化できます。下記の例を確認してください –
$physics = new Books( "Physics for High School", 10 ); $maths = new Books ( "Advanced Chemistry", 15 ); $chemistry = new Books ("Algebra", 7 ); /* Get those set values */ $physics->getTitle(); $chemistry->getTitle(); $maths->getTitle(); $physics->getPrice(); $chemistry->getPrice(); $maths->getPrice();
これにより、次の結果が生成されます。
Physics for High School Advanced Chemistry Algebra 10 15 7
デストラクタ
コンストラクタ関数と同様に、関数__destruct()を使ってデストラクタ関数を定義できます。デストラクタですべてのリソースを解放することができます。
継承
PHPクラス定義は、オプションでextends節を使用して親クラス定義から継承できます。構文は次のとおりです。
class Child extends Parent { <definition body> }
継承の効果は、子クラス(またはサブクラスまたは派生クラス)が次の特性を持つことです。
- 親クラスのすべてのメンバー変数宣言を自動的に持ちます。
- 自動的に親と同じメンバ関数をすべて持ちます(デフォルトでは、それらの関数が親で行うのと同じ方法で動作します)。
次の例では、Booksクラスを継承し、要件に基づいてより多くの機能を追加しています。
class Novel extends Books { var $publisher; function setPublisher($par){ $this->publisher = $par; } function getPublisher(){ echo $this->publisher. "<br />"; } }
今度は継承された関数を除いて、クラスNovelは2つの追加メンバ関数を保持します。
関数のオーバーライド
子クラスの関数定義は、親クラスの同じ名前の定義を上書きします。子クラスでは、親クラスから継承した関数の定義を変更できます。
次の例では、getPrice関数とgetTitle関数は、いくつかの値を返すようにオーバーライドされています。
function getPrice() { echo $this->price . "<br/>"; return $this->price; } function getTitle(){ echo $this->title . "<br/>"; return $this->title; }
パブリックメンバー
特に指定しない限り、クラスのプロパティとメソッドはpublicです。つまり、3つの可能な状況でアクセスすることができます。
- 宣言されているクラスの外から
- 宣言されているクラスの中から
- 宣言されているクラスを実装する別のクラスの中から
今まで、すべてのメンバーを一般のメンバーとして見てきました。クラスのメンバのアクセシビリティを制限したい場合は、クラスメンバをprivateまたはprotectedとして定義します。
プライベートメンバー
メンバーを非公開に指定することにより、メンバーが宣言されているクラスへのアクセスが制限されます。privateメンバーは、宣言されたクラスを継承し、クラスの外部からはアクセスできないクラスからは参照できません。
クラスメンバーは、メンバーの非公開キーワードinfrontを使用してプライベートにすることができます。
class MyClass { private $car = "skoda"; $driver = "SRK"; function __construct($par) { // Statements here run every time // an instance of the class // is created. } function myPublicFunction() { return("I'm visible!"); } private function myPrivateFunction() { return("I'm not visible outside!"); } }
場合MyClassのクラスを使用して別のクラスで延びて継承されるドライバを$れるように、myPublicFunction()は、表示されます。拡張クラスは、private宣言されているため、myPrivateFunctionと$ carを認識したりアクセスしたりすることはありません。
保護されたメンバー
保護されたプロパティまたはメソッドは、それが宣言されたクラスだけでなく、そのクラスを拡張するクラスでアクセス可能です。保護されたメンバーは、これらの2種類のクラス以外では利用できません。クラスメンバは、メンバの前にあるprotectedキーワードを使って保護することができます。
ここにはMyClassの別のバージョンがあります –
class MyClass { protected $car = "skoda"; $driver = "SRK"; function __construct($par) { // Statements here run every time // an instance of the class // is created. } function myPublicFunction() { return("I'm visible!"); } protected function myPrivateFunction() { return("I'm visible in child class!"); } }
インターフェイス
インタフェースは、実装者に共通の関数名を提供するように定義されています。異なる実装者は、それらの要件に応じてこれらのインタフェースを実装できます。インターフェイスは、開発者によって実装されるスケルトンです。
PHP5以降、このようなインターフェースを定義することは可能です –
interface Mail { public function sendMail(); }
次に、別のクラスがこのインタフェースを実装している場合、このように –
class Report implements Mail { // sendMail() Definition goes here }
定数
定数はある値を保持するという点で変数と似ていますが、定数は不変なので実際は関数のようです。定数を宣言すると、変更されません。
このバージョンのMyClassで行われているように、1つの定数を宣言するのは簡単です。
class MyClass { const requiredMargin = 1.7; function __construct($incomingValue) { // Statements here run every time // an instance of the class // is created. } }
このクラスでは、requiredMarginは定数です。これはキーワードconstで宣言されており、決して1.7以外のものに変更することはできません。変数名のように定数の名前に先頭に$が付いていないことに注意してください。
抽象クラス
抽象クラスはインスタンス化できず、継承されるクラスです。あなたはキーワードで抽象クラスを宣言抽象このように、 –
抽象クラスから継承する場合、親のクラス宣言でabstractとマークされたすべてのメソッドは、子によって定義されていなければなりません。さらに、これらのメソッドは同じ可視性で定義する必要があります。
abstract class MyAbstractClass { abstract function myAbstractFunction() { } }
抽象クラス内の関数定義の前には、キーワードabstractもなければならないことに注意してください。非抽象クラス内に抽象関数定義を持つことは合法ではありません。
静的キーワード
クラスメンバーまたはメソッドを静的として宣言すると、クラスのインスタンス化を必要とせずにアクセスできます。staticとして宣言されたメンバは、インスタンス化されたクラスオブジェクトではアクセスできません(静的メソッドでも可能です)。
次の例を試してみてください –
<?php class Foo { public static $my_static = 'foo'; public function staticValue() { return self::$my_static; } } print Foo::$my_static . "\n"; $foo = new Foo(); print $foo->staticValue() . "\n"; ?>
最終的なキーワード
PHP 5ではfinalキーワードが導入されています。これにより、子クラスが定義に接頭辞finalを付けることによってメソッドをオーバーライドできなくなります。クラス自体が最終的に定義されている場合は、拡張することはできません。
次の例では致命的なエラーが発生します:finalメソッドをオーバーライドできませんBaseClass :: moreTesting()
<?php class BaseClass { public function test() { echo "BaseClass::test() called<br>"; } final public function moreTesting() { echo "BaseClass::moreTesting() called<br>"; } } class ChildClass extends BaseClass { public function moreTesting() { echo "ChildClass::moreTesting() called<br>"; } } ?>
親コンストラクタを呼び出す
サブクラスのためのまったく新しいコンストラクタを書くのではなく、親のコンストラクタを明示的に呼び出してから、サブクラスのインスタンス化のために必要な作業をすべて実行してみましょう。ここに簡単な例があります –
class Name { var $_firstName; var $_lastName; function Name($first_name, $last_name) { $this->_firstName = $first_name; $this->_lastName = $last_name; } function toString() { return($this->_lastName .", " .$this->_firstName); } } class NameSub1 extends Name { var $_middleInitial; function NameSub1($first_name, $middle_initial, $last_name) { Name::Name($first_name, $last_name); $this->_middleInitial = $middle_initial; } function toString() { return(Name::toString() . " " . $this->_middleInitial); } }
この例では、2つの引数のコンストラクタを持つ親クラス(Name)と3つの引数を持つコンストラクタを持つサブクラス(NameSub1)があります。NameSub1のコンストラクタは、親コンストラクタを:: syntax(引数の2つを渡します)を使用して明示的に呼び出してから、追加のフィールドを設定して機能します。同様に、NameSub1は、オーバーライドする親関数の観点から非コンストラクターtoString()関数を定義します。