忍者ブログ

VB.NET-TIPS などプログラミングについて

VB.NETのTIPS(小技集)を中心に、Javascript、PHP その他のプログラミングについて少し役に立つ情報を発信します。いわゆる個人的な忘備録ですが、みなさんのお役に立てれば幸いです。

PHP クラス(class)の使い方について


今回はクラス(class)の使い方について説明します。
クラスと言えば、オブジェクト指向型のデータ処理と言われていますが、 そこまで固く考えなくても、ある処理を行うにあたって必要なデータや関数をまとめたものと言えると思います。

クラスの宣言としては以下の様に行います。(実際の処理では無く日本語で記述しています)

class クラス名
{
    //  プロパティの宣言(外部から操作可能)
    public $変数名[ = 値];

    //  内部プロパティの宣言(外部から操作できない)
    private $変数名[ = 値];

    //  メソッドの宣言
    public function メソッド名(){
        メソッド内処理...
    }

    //  内部メソッドの宣言
    private function メソッド名(){
        メソッド内処理...
    }

    //  コンストラクタ(クラス生成時に呼ばれる関数)
    function __construct() {
        クラスの初期処理
    }

    //  デストラクタ(クラス破棄時に呼ばれる関数)
    function __destruct() {
        クラスの終了処理
    }
}


プロパティの宣言は public, private でしますが public 宣言されたプロパティは、 クラスの外部からの参照が可能で private 宣言されたプロパティは、クラス内でのみ参照できます。

また、メソッド宣言も同様で public 宣言されたメソッドは、クラスの外部からの呼出しができますが、 private 宣言されたメソッドは、クラス内でのみ呼出しできます。

ここで示した、コンストラクタ及びデストラクタはそれぞれ、クラスのインスタンス生成時及び、破棄時に呼び出される関数で、 必要無ければ宣言する必要はありません。






■簡単なクラス の宣言例

「クラス」宣言とそのクラスを生成し実行する処理を1個のファイルの中で実現しています。 (実際問題としては、クラスの宣言のみを別ファイルにし、それを利用するファイルの先頭で include などで取り込むこともできます。)

以下のソースでは名前用のクラスとして「nameClass」として宣言しています。 プロパティの宣言として「姓名」の「姓」と「名」の部分に分けて退避できる様にし、 「姓名」としてのフル名称を取得するメソッドの宣言を行っています。 (このクラスは特に有用なものではありませんので悪しからず...)

更に、コンストラクタで「姓」と「名」に分けて引数で与える様にしています。 コンストラクタはクラスのインスタンスを生成する場合に new 命令の後にクラス名を記述し、 そのクラス名のカッコの中に引数を記述します。

<?php
//  名前用のクラス
class nameClass
{
    //  プロパティの宣言
    public $familyName = "";
    public $lastName = "";

    //  メソッドの宣言
    public function getFullName(){
        return $this->familyName." ".$this->lastName;
    }

    //  コンストラクタ()
    function __construct($_familyName, $_lastName) {
        //  クラスの初期処理
        $this->familyName = $_familyName;
        $this->lastName   = $_lastName;
    }
}

//  [nameClass]クラスの生成
$clsName = new nameClass("Tanaka", "Taro");
//  フル名のメソッド呼出
$strName = $clsName->getFullName();
//  表示
echo "FullName:".$strName."<br>\n";

//  ブラウザ表示
//FullName:Tanaka Taro
?>

上記のメソッドの宣言、及びコンストラクタの中で $this が出てきていますが、これは自分自身のオブジェクト(インスタンス)を示すものです。 クラス内の変数やメソッドを参照する場合には $this の後にアロー演算子の -> を用いてアクセスします。
アロー演算子はインスタンスに対するものですので、クラスを生成した後でそのメソッドを呼び出す場合にも用います。

クラスのインスタンスから直接内部の変数がアクセスできるのは嫌な場合は、変数アクセス用のプロパティ設定メソッドを作成し、以下の様にします。 また、クラスのインスタンス生成時に引数の値が指定できない場合も在ると思いますので、コンストラクタの引数に省略できるデフォルト引数値を用いています。

//  名前用のクラス
class nameClass
{
    //  プロパティの宣言
    private $familyName;
    private $lastName;

    //  プロパティ用メソッドの宣言
    public function setFamilyName($_familyName){
        $this->familyName = $_familyName;
    }
    public function setLastName($_lastName){
        $this->lastName = $_lastName;
    }

    //  フル名前を返すメソッドの宣言
    public function getFullName(){
        return $this->familyName." ".$this->lastName;
    }

    //  コンストラクタ(デフォルト引数)
    function __construct($_familyName = "", $_lastName = "") {
        //  クラスの初期処理(メソッドを使ってみました)
        $this->setFamilyName($_familyName);
        $this->setLastName($_lastName);
    }
}

//  [nameClass]クラスの生成
$clsName = new nameClass();
//  プロパティ用のメソッド呼出
$clsName->setFamilyName("Tanaka");
$clsName->setLastName("Taro");
//  フル名のメソッド呼出
$strName = $clsName->getFullName();
//  表示
echo "FullName:".$strName."<br>\n";

//  ブラウザ表示
//FullName:Tanaka Taro


■クラスの 継承(extends) の使い方の例

継承 とは基となるクラスの性質を引き継いで、さらに機能を増やしたい場合に使う方法です。
クラスを宣言する時に extends で親クラスを指定します。

以下の例は親クラスとして「cName」を宣言し、それを継承したクラス「cPerson」を宣言しています。
クラス「cPerson」は、クラス「cName」で宣言されたプロパティ、メソッドを全て引き継ぎ、 さらに「cPerson」内で宣言されたプロパティ、メソッドをものを持ちます。

//  継承の基となる親クラス:[cName]
class cName
{
    //  プロパティの宣言
    public $familyName = "";
    public $lastName = "";

    //  メソッドの宣言
    public function getFullName(){
        return $this->familyName." ".$this->lastName;
    }
}

//  [cName]から派生した子クラス:[cPerson]
class cPerson extends cName
{
    //  プロパティの宣言
    public $address = "";

    //  メソッドの宣言
    public function getAddress(){
        return $this->address;
    }
}

//  [cPerson]クラスの生成
$insPerson = new cPerson();

//  親クラスのプロパティ設定
$insPerson->familyName = "Tanaka";
$insPerson->lastName = "Taro";
//  子クラスのプロパティ設定
$insPerson->address = "Tokyo";
//  フル名のメソッド呼出,表示
echo "FullName:".$insPerson->getFullName()."<br>\n";
//  住所取得のメソッド呼出,表示
echo "Address:".$insPerson->getAddress()."<br>\n";

//  ブラウザ表示
//FullName:Tanaka Taro
//Address:Tokyo



■プロパティの アクセス権(public, protected, private) について

プロパティのアクセス権の指定ですが public, protected, private の種類があります。

PHP の公式の説明によりますと「 public 宣言されたクラスのメンバーには、どこからでもアクセス可能です。 protected 宣言されたメンバーには、 そのクラス自身、そのクラスを継承したクラス、および親クラスからのみアクセスできます。 private 宣言されたメンバーには、そのメンバーを定義したクラスからのみアクセスできます。 」と記されています。

以下に アクセス権(public, protected, private) の例を示します。

<?php
class cAccess
{
    //  プロパティの宣言
    public      $_pub = "public"."<br>\n";
    protected   $_pro = "protected"."<br>\n";
    private     $_pri = "private"."<br>\n";

    //  メソッドの宣言
    public function echoAll(){
        echo "public:"   .$this->_pub;
        echo "protected:".$this->_pro;
        echo "private:"  .$this->_pri;
    }
}

//  [cAccess]クラスの生成
$insAcc = new cAccess();
//  プロパティ参照,表示
echo "public:"   .$insAcc->_pub;
echo "protected:".$insAcc->_pro;  //  エラーが発生する
echo "private:"  .$insAcc->_pri;  //  エラーが発生する
//  メソッド呼出
$insAcc->echoAll();
?>

これを実行するとブラウザに以下の様にエラーが表示されます。

public:public

Fatal error: Cannot access protected property cAccess::$_pro in C:\xampp\htdocs\_test\class4.php on line 21

そこで21行目をコメントにして実行すると以下の様にエラーが表示されます。

public:public

Fatal error: Cannot access private property cAccess::$_pri in C:\xampp\htdocs\_test\class4.php on line 22

クラスの外側から protected, private と宣言されたものはアクセスができないので、 さらに22行目をコメント化して再度実行すると以下の様な表示となります。

public:public
public:public
protected:protected
private:private


そこでクラス「cAccess」から派生した「cAccess2」を宣言し、そのメソッドの中で、 「cAccess」の protected 宣言のプロパティがアクセスできることを示します。

<?php
class cAccess
{
    //  プロパティの宣言
    public      $_pub = "public"."<br>\n";
    protected   $_pro = "protected"."<br>\n";
    private     $_pri = "private"."<br>\n";

    //  メソッドの宣言
    public function echoAll(){
        echo "echoAll...<br>\n";
        echo "public:"   .$this->_pub;
        echo "protected:".$this->_pro;
        echo "private:"  .$this->_pri;
    }
}

class cAccess2 extends cAccess
{
    //  メソッドの宣言
    public function echoAll2(){
        echo "echoAll2...<br>\n";
        echo "public:"   .$this->_pub;
        echo "protected:".$this->_pro;  //  アクセス可能
        echo "private:"  .$this->_pri;  //  未定義のNotice警告!!
    }
}

//  [cAccess2]クラスの生成
$insAcc2 = new cAccess2();
//  親クラスメソッド呼出
$insAcc2->echoAll();
//  メソッド呼出
$insAcc2->echoAll2();
?>

これを実行するとブラウザに以下の様に警告が表示されますが protected 宣言のプロパティがアクセスできることが分かります。

echoAll...
public:public
protected:protected
private:private
echoAll2...
public:public
protected:protected

Notice: Undefined property: cAccess2::$_pri in C:\xampp\htdocs\_test\class5.php on line 25
private:



■メソッドの アクセス権(public, protected, private) について

クラスメソッドのアクセス権においてもプロパティ同様 public, protected, private の種類があります。 アクセス権を明示せずに宣言したメソッドは public となります。

<?php
class cAccess
{
    //  publicメソッドの宣言
    public    function pubFunc(){
        echo "public...<br>\n";
    }
    //  protectedメソッドの宣言
    protected function proFunc(){
        echo "protected...<br>\n";
    }
    //  privateメソッドの宣言
    private   function priFunc(){
        echo "private...<br>\n";
    }

    function Func(){
        $this->pubFunc();
        $this->proFunc();
        $this->priFunc();
    }
}

//  [cAccess]クラスの生成
$insAcc = new cAccess();
//  クラスメソッド呼出
$insAcc->pubFunc();
$insAcc->proFunc();		//	エラー発生!!
$insAcc->priFunc();		//	エラー発生!!
$insAcc->Func();
?>

これを実行するとブラウザに以下の様にエラーが表示されます。

public...

Fatal error: Call to protected method cAccess::proFunc() from context '' in C:\xampp\htdocs\_test\class6.php on line 28

そこで28行目をコメントにして実行すると以下の様にエラーが表示されます。

public...

Fatal error: Call to private method cAccess::priFunc() from context '' in C:\xampp\htdocs\_test\class6.php on line 29

クラスの外側から protected, private と宣言されたメソッドはアクセスができないので、 さらに29行目をコメント化して再度実行すると以下の様な表示となります。
クラス内部のメソッドでは全てのメソッドがアクセス可能です。

public...
public...
protected...
private...

オーバーライド(public function) の使い方の例

プロパティ(変数)、メソッド(関数)は同じ名前を子クラスに定義すれば、親クラスのプロパティ(変数)、メソッド(関数)を上書きすることができます。
この上書きができることで子クラスでは、親クラスとは異なる動作をさせることができます。以下にその例を示します。

<?php
//  継承の基となる親クラス
class cName
{
    //  プロパティの宣言
    public $familyName = "";
    public $lastName = "";

    //  メソッドの宣言
    public function getFullName(){
        return $this->familyName." ".$this->lastName;
    }
}

//  [cName]から派生した子クラス
class cPerson extends cName
{
    //  メソッドの宣言
    public function getFullName(){
        return "FullName:".$this->familyName." ".$this->lastName;
    }
}

//  [cPerson]クラスの生成
$insPerson = new cPerson();

//  親クラスのプロパティ設定
$insPerson->familyName = "Tanaka";
$insPerson->lastName = "Taro";
//  子クラスのメソッド呼出,表示
echo $insPerson->getFullName()."<br>\n";

//  ブラウザ表示
//FullName:Tanaka Taro
?>

子クラスの「getFullName()」メソッドは親クラスのものを上書きしており、メソッドを呼び出すと親クラスのメソッドは呼び出されず 子クラスのメソッドが呼び出されます。

尚、子クラスの「getFullName()」メソッドは親クラスのものを呼出して処理することもできます。
子クラスから親クラスのメソッドを呼び出す場合には parent:: を使います。上記のソースを一部変更します。

<?php
//  継承の基となる親クラス
class cName
{
    //  プロパティの宣言
    public $familyName = "";
    public $lastName = "";

    //  メソッドの宣言
    public function getFullName(){
        return $this->familyName." ".$this->lastName;
    }
}

//  [cName]から派生した子クラス
class cPerson extends cName
{
    //  メソッドの宣言
    public function getFullName(){
        return "FullName:".parent::getFullName();
    }
}

//  [cPerson]クラスの生成
$insPerson = new cPerson();

//  親クラスのプロパティ設定
$insPerson->familyName = "Tanaka";
$insPerson->lastName = "Taro";
//  フル名のメソッド呼出,表示
echo $insPerson->getFullName()."<br>\n";
?>

■コンストラクタ、デストラクタでの オーバーライド の注意点

コンストラクタ、デストラクタもオーバーライドが出来るのですが、少し注意が必要です。取敢えず以下のソースを見て下さい。
親クラスと子クラスを宣言していますが、中身はコンストラクタ、デストラクタの処理のみを行います。
<?php
//  継承の基となる親クラス
class cParent
{
    //  コンストラクタ
    function __construct() {
        echo "cParent__construct<br>\n";
    }
    //  デストラクタ
    function __destruct() {
        echo "cParent__destruct<br>\n";
    }
}

//  [cParent]から派生した子クラス
class cChild extends cParent
{
    //  コンストラクタ
    function __construct() {
        echo "cChild__construct<br>\n";
    }
    //  デストラクタ
    function __destruct() {
        echo "cChild__destruct<br>\n";
    }
}

//  [cParent]クラスの生成
$insParent = new cParent();
//  [cParent]クラスの廃棄
unset($insParent);

//  [cChild]クラスの生成
$insChild = new cChild();
//  [cChild]クラスの廃棄
unset($insChild);
?>
これを実行するとブラウザに以下の様に表示されます。
子クラスの生成時に、子クラスのコンストラクタのみが呼び出され、親クラスのコンストラクタは呼び出されません。
また、子クラスの廃棄時に、子クラスのデストラクタのみが呼び出され、親クラスのデストラクタは呼び出されません。
cParent__construct
cParent__destruct
cChild__construct
cChild__destruct

子クラスは親クラスから派生しているので、当然、親クラスのコンストラクタ、デストラクタを呼出したいことはよくあります。
そこで、子クラスのコンストラクタ、デストラクタの中で、親クラスのコンストラクタ、デストラクタを呼出してやります。以下のソースをを見て下さい。
<?php
//  継承の基となる親クラス
class cParent
{
    //  コンストラクタ
    function __construct() {
        echo "cParent__construct<br>\n";
    }
    //  デストラクタ
    function __destruct() {
        echo "cParent__destruct<br>\n";
    }
}

//  [cParent]から派生した子クラス
class cChild extends cParent
{
    //  コンストラクタ
    function __construct() {
        parent::__construct();
        echo "cChild__construct<br>\n";
    }
    //  デストラクタ
    function __destruct() {
        parent::__destruct();
        echo "cChild__destruct<br>\n";
    }
}

//  [cChild]クラスの生成
$insChild = new cChild();
//  [cChild]クラスの廃棄
unset($insChild);
?>
これを実行するとブラウザに以下の様に表示されます。
cParent__construct
cChild__construct
cParent__destruct
cChild__destruct












PR

コメント

コメントを書く