PHP5ではプロパティを持っていてもいなくても常に“空ではない”と評価。
“PHP5ではオブジェクトは常に「TRUE」と評価”される。
▼生成したオブジェクトを「empty()」関数で“空”であるか否かを確認
▼結果
/demo/object3_evaluation.html
「インターフェイス」は「extends」を使って、他の「インターフェイス」を継承して拡張することができる。また、その場合は、「,(コンマ)」で区切って複数指定できる。
▼結果
/demo/interface2_extends.html
「インターフェイスを実装したクラス」を継承したクラスも、「インターフェイスを継承したインターフェイス」を実装したクラスも、そのクラスは「継承元のインターフェイスを実装」していると見做される。
▼結果
/demo/interface3.html
オブジェクト引数のインターフェイス指定
「関数」や「クラスのメンバ関数」の定義時には、「オブジェクト引数のクラス指定」だけではなく「オブジェクト引数のインターフェイス指定」もできる。この場合、渡されたオブジェクトが、指定された「インターフェイス」を実装しているか否かがチェックされる。
▼結果
/demo/interface4_object.html
定義済みのインターフェイス
PHPには予め幾つかの「インターフェイス」が定義されている。
定義済みの「インターフェイス」を確認してみる。
▼結果
/demo/interface5_already.html
▼結果
/demo/object4_4-5.html
PHP5におけるオブジェクトを比較した際の評価の違い
“PHP5ではオブジェクトは常に「TRUE」と評価”される。
▼生成したオブジェクトを「empty()」関数で“空”であるか否かを確認
<pre>
<?php
class C1{
var $var;
}
class C2{
//
}
echo "[PHP".substr(PHP_VERSION, 0, 1), ]\n";//substr(string $string , int $start [, int $length ] )文字列 string の、start で指定された位置から length バイト分の文字列を返す
echo "[PHP".PHP_VERSION, ]\n";
$c1 = new C1;
$c2 = new C2;
var_dump(empty($c1)); //empty ? 変数が空であるかどうかを検査。プロパティ(var $var;)を持つオブジェクト
var_dump(empty($c2)); //プロパティを持たないオブジェクト
unset($c1->var);//unset ? 指定した変数の割当を解除
$c2->var = NULL;
var_dump(empty($c1)); //持っていたプロパティをアンセット
var_dump(empty($c2)); //プロパティをセット(NULL)した
?>
</pre>
▼結果
/demo/object3_evaluation.html
「インターフェイス」は「extends」を使って、他の「インターフェイス」を継承して拡張することができる。また、その場合は、「,(コンマ)」で区切って複数指定できる。
<pre>
<?php
interface I1{
const I1_CONST = "インターフェイス1定数";
function m1();
}
interface I2{
const I2_CONST = "インターフェイス2定数";
function m2();
}
#「インターフェイス」を継承
interface I3 extends I1, I2{
// const I1_CONST = "ダミー"; //「インターフェイス定数」再定義は不可 ⇒ Fatal error: Cannot inherit previously-inherited constant I1_CONST from interface I1
}
#「インターフェイス」実装
class I4 implements I1, I2{
public function m1(){
//
}
public function m2(){
//
}
}
#「インターフェイス」実装
class C1 implements I3{
public function m1(){
//
}
public function m2(){
//
}
}
?>
</pre>
▼結果
/demo/interface2_extends.html
「インターフェイスを実装したクラス」を継承したクラスも、「インターフェイスを継承したインターフェイス」を実装したクラスも、そのクラスは「継承元のインターフェイスを実装」していると見做される。
<pre>
<?php
#「インターフェイス」の定義
interface I1{
//
}
interface I2 extends I1{//インターフェイスを継承したインターフェイス
//
}
#「インターフェイス」の実装
abstract class C1Base implements I1{//インターフェイスを実装したクラス
//
}
class C2 extends C1Base{//「インターフェイスを実装したクラス」を継承したクラス
//
}
class C3 implements I2{//「インターフェイスを継承したインターフェイス」を実装したクラス
//
}
#オブジェクトが実装する「インターフェイス」を調べる
$imp_arr["C2] = class_implements(new C2);//「class_implements()」関数 ⇒ 「指定したオブジェクトが実装するインターフェイス名を配列に格納して返す」
$imp_arr["C3] = class_implements(new C3);
print_r($imp_arr);
?>
</pre>
▼結果
/demo/interface3.html
オブジェクト引数のインターフェイス指定
「関数」や「クラスのメンバ関数」の定義時には、「オブジェクト引数のクラス指定」だけではなく「オブジェクト引数のインターフェイス指定」もできる。この場合、渡されたオブジェクトが、指定された「インターフェイス」を実装しているか否かがチェックされる。
<pre>
<?php
interface I1{}
interface I2{}
interface I3 extends I1, I2{}//複数インターフェイスを継承したインターフェイス
interface I4{}
abstract class C1Base implements I3{}//インターフェイスを実装したクラス
class C1 extends C1Base{}//「インターフェイスを実装したクラス」を継承したクラス
function f1(C1Base $obj){//②
echo '$obj は、\'C1Base\'のインスタンスじゃなきゃダメ。', "\n";
echo '$obj は、\'', get_class($obj), "'のインスタンス。\n\n";
}
function f2(I1 $obj){//④
echo '$obj は、\'I1\'インターフェイスの実装じゃなきゃダメ。', "\n";
echo '$obj implements...', "\n";
print_r(class_implements($obj));
}
function f3(I4 $obj){
echo '$obj must implement interface \'I4\'.', "\n";
echo '$obj implements...', "\n";
print_r(class_implements($obj));
}
f1(new C1);//①
f2(new C1);//③
//f3(new C1); //インターフェイス「I4」を実装していなければならない ⇒ Catchable fatal error: Argument 1 passed to f3() must implement interface I4, instance of C1 given, called
?>
</pre>
▼結果
/demo/interface4_object.html
定義済みのインターフェイス
PHPには予め幾つかの「インターフェイス」が定義されている。
定義済みの「インターフェイス」を確認してみる。
<pre>
<?php
#定義済み「インターフェイス」と定義されるメソッド名を取得・出力
foreach(get_declared_interfaces() as $interface_name)//get_declared_interfaces ? 宣言されている全てのインターフェースの配列を返す
$interfaces[$interface_name] = get_class_methods($interface_name);//get_class_methods ? クラスメソッドの名前を取得
print_r($interfaces);
echo "
";
#定義済み「インターフェイス」を実装する定義済みクラス名を抽出・出力
foreach(get_declared_classes() as $class_name){
$buf_arr = array();
$class_abj = new ReflectionClass($class_name);
$imp_arr = $class_abj->getInterfaces();
foreach($imp_arr as $imp_obj){
$imp_arr_ = get_object_vars($imp_obj);
$buf_arr[] = $imp_arr_["name];
}
if(count($buf_arr))
$arr[$class_name] = $buf_arr;
}
print_r($arr);
?>
</pre>
▼結果
/demo/interface5_already.html
<pre>
<?php
function compare($param1, $param2){ #2つのオブジェクトを比較する関数を定義
#変数名を利用して変数へのリファレンスを取得
$obj1 =& $GLOBALS[$param1];
$obj2 =& $GLOBALS[$param2];
$param1 = '$'.$param1;
$param2 = '$'.$param2;
if(is_null($obj2))
return "N/A";
$str = $param1;
if($obj1 === $obj2)
$str .= " === ";
else if($obj1 == $obj2)
$str .= " == ";
else
$str .= " != ";
return $str.$param2;
}
#全く同じ構造をした2つのクラスを定義
class C1{
public $p1 = "プロパティ値1";
}
class C2{
public $p1 = "プロパティ値1";
}
$c1 = new C1;//①生成した「C1」クラスのインスタンスオブジェクトを「変数$c1」に結びつける
$c1Dis = new C1;//②生成した「C1」クラスのインスタンスオブジェクトを別の「変数$c1Dis」に結びつける
if(substr(PHP_VERSION, 0, 1) == 5){ #PHP5用の処理
$c1Ass = $c1;//「変数$c1Ass」に「変数$c1」を“割り当て”。「変数$c1Ass」に「変数$c1」と共通の「リファレンス(同じ変数の内容を異なった名前でコールすること。実体の別名)」をセット
$c1Clo = clone($c1); //「変数$c1Clo」に「変数$c1」のクローン(コピー)を代入。「clone $c1」はPHP4では不可(PHP5からという意)
$c1CloDis = clone($c1);//「変数$c1CloDis」に「変数$c1」のクローン(コピー)を代入
}else{ #PHP4用の処理
$c1Ass = NULL;
$c1Clo = $c1;
$c1CloDis = $c1;
}
$c1CloDis->p1 = "プロパティ値2";//「変数c1CloDis」のプロパティを更新
$c1Ref =& $c1;//「変数$c1Ref」に「変数$c1」へのリファレンスを代入
$c2 = new C2;//「変数c2」に「C1」クラスと全く同じ構造をした「C2」クラスのオブジェクトを代入
echo "[PHP".substr(PHP_VERSION, 0, 1), ]\n";//③
#比較する変数(オブジェクト)名を指定して結果を出力
echo
compare('c1', 'c1Dis'), "\n", //④比較対照 - 同じクラスの別オブジェクト ⇒ ==
compare('c1', 'c1Ass'), "\n", //比較対照 - 自身を割り当てられた変数 ⇒ ===
compare('c1', 'c1Clo'), "\n", //比較対照 - 自身のクローン ⇒ ==
compare('c1', 'c1CloDis'), "\n", //比較対照 - 自身のクローン(プロパティを更新) ⇒ !=
compare('c1', 'c1Ref'), "\n", //比較対照 - 自身へのリファレンスを格納した変数 ⇒ ===
compare('c1', 'c2');//比較対照 - 同じ構造の別クラスのオブジェクト ⇒ !=
?>
</pre>
▼結果
/demo/object4_4-5.html
PHP5におけるオブジェクトを比較した際の評価の違い
比較対照 | PHP5 | 演算子 |
---|---|---|
同じクラスの別オブジェクト | 一致 | == |
自身を割り当てられた変数 | 完全一致 | === |
自身のクローン | 一致 | == |
自身のクローン(プロパティを更新) | 不一致 | != |
自身へのリファレンスを格納した変数 | 完全一致 | === |
同じ構造の別クラスのオブジェクト | 不一致 | != |