クラス


クラスを定義する(class)

class [クラス名]{} の様に定義します。
メンバー変数にデフォルト値を設定できます。
thisキーワードをつけることでそのクラスのメンバー変数、メンバー関数にアクセスします。

class Simple {
    private $var = 1;

    public function func(){
        echo $this->var . "\n";
    }

    public function func2(){
        $this->func();
    }
}

$c = new Simple();
$c->func();

コンストラクタ、デストラクタを定義する(__construct,__destruct)

__construct,__destructを関数名として定義します。

class Simple2{
    public function __construct(){    echo "construct \n";    }
    public function __destruct(){    echo "destruct \n";     }
}

$c = new Simple2();
echo "new \n";
//  => construct
//       new
//       destruct

メンバー関数をオーバーライドする

protected,publicなメンバー関数を派生クラスで定義することでオーバーライドされます。

//基底クラス
class Base2{
    protected function print_protected(){
        echo "Base print_protected \n";
    }
    public function print_public(){
        $this->print_protected();
        echo "Base print_public \n";
    }
}
// 派生クラス
class Derivation2 extends Base2{

//    protected function print_protected(){
//        echo "Derivation print_protected \n";
//    }

    public function print_public(){
        $this->print_protected();
        echo "Derivation print_public \n";
    }
}
// 結果
$c = new Derivation2();
$c->print_public();

//  => 
//    Base print_protected 
//    Derivation print_public

定数を定義する(const)

クラスは定数をdefineではなくconstを付けて定義できます。$を付けない点に注意が必要です。
定数のアクセス制限はできません。クラス内ではself::を付け、クラスの外では[クラス名]::を付けて呼び出します。

class ConstClass {
    const  CONST_VAR = 1;

    public function func(){
        echo self::CONST_VAR . "\n";
    }
}

$c = new ConstClass();
echo ConstClass::CONST_VAR . "\n";    // => 1
ConstClass::func();    // => 1

静的メンバー変数、関数を定義する

static修飾子をつけます。クラス内ではself修飾子をつけて呼び出します。
クラスの外ではクラス名にスコープ定義演算子をつけて呼び出します。

class StaticClass {
    public static  $var = 1;

    public function func(){
        echo self::$var . "\n";
    }
    public static function static_func(){
        echo "static func \n";
    }
}

$c = new StaticClass();
echo StaticClass::$var . "\n";    // => 1
StaticClass::static_func();    // => static func

継承クラスを定義する(extends)

クラス名の後にextends キーワードをつけて継承するクラスを指定します。多重継承はできません。
親クラスの関数はparent::をつけて呼び出します。親の親クラスの関数を直接呼び出すことはできません。明示的に基底クラスのコンストラクタやデストラクタを呼び出さなければ呼び出されません。

//基底クラス
class Base{
    public function __construct(){    echo "Base construct \n";    }
    public function __destruct(){    echo "Base destruct \n";    }
}
// 派生クラス
class Derivation extends Base{
    public function __construct(){
        parent::__construct();
        echo "Derivation construct \n";
    }
    public function __destruct(){
        echo "Derivation destruct \n";
        parent::__destruct();
    }
}
// 結果
$c = new Derivation();
echo "Drivation new \n";
//  => 
//    Base construct 
//    Derivation construct 
//    Drivation new 
//    Derivation destruct 
//    Base destruct

抽象クラスを定義する(abstract)

クラスと抽象化したい関数の前にabstract修飾子をつけます。
抽象クラスのインスタンスは生成できません。継承先で定義することを強制します。
アクセス制限はそれ以上に厳しくすることはできません。(publicをprotectedにするなど。)

abstract class AbstractClass {
    protected $var = 1;    // => 変数などは宣言しておける

    abstract public function func();
}

class AbstractDef extends AbstractClass{
    // => 定義しないと致命的なエラーとなる
    public function func(){ 
        echo "abstract definition \n";
    }   
}

// $a = new AbstractClass();    // => Fatal error
$ad = new AbstractDef();
$ad->func();    // => abstract definition 

ページトップ


インターフェイスクラスを定義する(interface)

interface修飾子をclassの代わりに使用します。interface インターフェイス名{}
インターフェイスクラスを継承するにはimplementsを使用します。メンバー変数を持つことはできません。

interface iClass {
    public function func();
}

class iClassDef implements iClass{
    // => 定義しないとFatal error
    public function func(){ 
        echo "interface definition \n";
    }   
}

$id = new iClassDef();
$id->func();    // => interface definition 

インターフェイスクラスは多重継承できます。さらに通常の継承クラスを1つ継承できます。

interface iClass2 {
    public function func2();
}
class AnyClass{
    public function any_func(){
        echo "AnyClass func\n";
    }
}

class iClassDef2 extends AnyClass implements iClass, iClass2{
    public function func(){ 
        echo "interface definition \n";
    }   
    public function func2(){ 
        echo "interface definition2 \n";
    }   
}

$id = new iClassDef2();
$id->func();    // => interface definition 
$id->func2();    // => interface definition2 

継承を抑制する(final)

final修飾子を使用します。関数につけると関数のオーバーライドを抑制し、クラスにつけると継承を抑制します。
クラス継承の抑制

final class finalClass {
    public function func(){
        echo "final class func\n";
    }
}
//  class ExFinalClass extends finalClass{}    // => Parse error

関数オーバーライドの抑制

class finalFuncClass {
    final public function func(){
        echo "final  func\n";
    }
}
class ExFinalFuncClass extends finalFuncClass{
//    public function func(){}    // => Fatal error
}


クラスの名前を調べる(get_class)

get_class()を使います。

class A{
    public $a;
}
class B extends A{
    public $b;
}

$a = new A();
$b = new B();

echo get_class($a) . "\n";    // => A
echo get_class($b) . "\n";    // => B

親クラスの名前を調べる(get_parent_class)

get_parent_class()を使います。親クラスは1つ上の親クラスになります。

class A1{
    public $a1;
}
class A2 extends A1{
    public $a2;
}
class A3 extends A2{
    public $a3;
}

$a1 = new A1();
$a2 = new A2();
$a3 = new A3();

echo get_parent_class($a1) . "\n";    // => 
echo get_parent_class($a2) . "\n";    // => A1
echo get_parent_class($a3) . "\n";    // => A2

オブジェクトが指定した派生クラスかどうか調べる(is_a)

is_a()を使います。

class B1{
    public $b1;
}
class B2 extends B1{
    public $b2;
}
class B3 extends B2{
    public $b3;
}

$b1 = new B1();
$b2 = new B2();
$b3 = new B3();

echo is_a($b1, "B1") . "\n";    // => true
echo is_a($b2, "B1") . "\n";    // => true
echo is_a($b3, "B1") . "\n";    // => true

未定義変数、関数の使用を捕捉する(__set,__get,__call,__callStatic)

変数は__set(),__get()を定義します。関数は__call(), __callStatic()を定義します。

class C{
    public $c1;
    // 未定義変数への代入を捕捉する
    public function __set($name, $value){
        echo "set name: " . $name . " value: " . $value . "\n";
    }
    // 未定義変数からの代入を捕捉する
    public function __get($name){
        echo "get name: " . $name . "\n";
    }

    // 未定義関数の使用を捕捉する
    public function __call($name, $arguments){
        $msg = "call name: " . $name . " arguments: ";
        foreach($arguments as $a){ $msg .= $a . " ";  }
        echo $msg . "\n";
    }
    // version5.3以降
    // 未定義静的関数の使用を捕捉する
    public static function __callStatic($name, $arguments){
        $msg = "call static name: " . $name . " arguments: ";
        foreach($arguments as $a){ $msg .= $a . " ";  }
        echo $msg . "\n";
    }
}

$c = new C();
$c->set_dummy = 12;    // => "set name: set_dummy value: 12"
$var = $c->get_dummy;    // => "get name: get_dummy"
$c->test(1, "arg");    // => call name: test arguments: 1 arg
C::staticTest(5, "static test");    // => call static name: staticTest arguments: 5 static test 

クラスオブジェクトをコピーする(clone)

cloneを使います。

class D{
    public $str;
}
// 元のオブジェクト
$base = new D();
$base->str = "base";
echo $base->str . "\n";    // => base

// クローンを使えば元のインスタンスは変わらない
$clone = clone $base;
$clone->str = "clone";
echo $base->str . "\n";    // => base
echo $clone->str . "\n";    // => clone

// 普通に代入するだけでは元のインスタンスも変わってしまう
$ref = $base;
$ref->str = "ref";
echo $base->str . "\n";    // => ref
echo $ref->str . "\n";    // => ref

メンバー変数がクラスオブジェクトの場合は参照がコピーされるので、(シャローコピー)、__clone()を使った明示的なクローン指示が必要です。

__clone()を定義しないと・・

class D2{
    public $obj;
}
// クラスオブジェクトを持つ元のオブジェクト
$base = new D2();
$base->obj = new D();
$base->obj->str = "base";
echo $base->obj->str . "\n";    // => base

// 元のオブジェクトまで変化してしまう
$clone = clone $base;
$clone->obj->str = "clone";
echo $base->obj->str . "\n";    // => clone
echo $clone->obj->str . "\n";    // => clone

__clone()を定義する。

class D3{
    public $obj;
    public function __clone(){
        // 明示的なクローン指示が必要
        $this->obj = clone $this->obj;
    }
}
// クラスオブジェクトを持つ元のオブジェクト
$base = new D3();
$base->obj = new D();
$base->obj->str = "base";
echo $base->obj->str . "\n";    // => base

// 元のオブジェクトは変化しない!
$clone = clone $base;
$clone->obj->str = "clone";
echo $base->obj->str . "\n";    // => base
echo $clone->obj->str . "\n";    // => clone

クラスの文字列変換方法を決める(__toString)

__toString()を使います。
通常文字列として扱えないクラスを、文字列として扱った場合の動作を決めます。

class E{
    public function __toString(){
        return "Hello";
    }
}

$e = new E();
echo $e . " World!\n";    // => Hello World!

オブジェクトを比較する

一致演算子===は同じインスタンスなら等しく、比較演算子==はこれに加えて属性の値も同じでなければならない。

同じクラスの場合

class F{
    public $var;
    public function __construct($var){  $this->var = $var;  }
}

// まったく同じオブジェクトとの比較
$f1 = new F(5);
$f2 = $f1;
echo ($f1==$f2) . "\n";    // => 1
echo ($f1===$f2) . "\n";    // => 1

// 違うオブジェクトとの比較
$f2 = new F(5);
echo ($f1==$f2) . "\n";    // => 1
echo ($f1===$f2) . "\n";    // => 0

// 持っている変数の値も違う場合
$f2->var = 7;
echo ($f1==$f2) . "\n";    // => 0
echo ($f1===$f2) . "\n";    // => 0

違うクラスとの比較は当然false

class FF{
    public $var;
    public function __construct($var){  $this->var = $var;  }
}
$f2 = new FF(5);
echo ($f1==$f2) . "\n";    // => 0
echo ($f1===$f2) . "\n";    // => 0