PHPのオブジェクトと参照渡し

2015年1月27日(火)
原田 裕介(はらだゆうすけ)

オブジェクト

オブジェクトを作成するにはnewを使います。通常は、4_6_1.phpのように記述します。

4_6_1.php

<?php
class Color{
  public $color = null;
  public function __construct(){
    $this->color = 'red';
  }
  public function getColor(){
    return $this->color;
  }
}

$Color = new Color();
echo $Color->getColor();

出力結果

>php 4_6_1.php
red

他にも4_6_2.phpのような書き方も可能です。このように、変数に関数名を格納しておいて、動的に呼び出す仕組みを可変関数と呼びます。

4_6_2.php

<?php
class Color{
  public $color = null;
  public function __construct(){
    $this->color = 'red';
  }
  public function getColor(){
    return $this->color;
  }
}

$class = 'Color';
$Color = new $class;
echo $Color->getColor();

出力結果

>php 4_6_2.php
red

可変関数といって変数に関数名を格納しておいて動的に呼び出すことも可能です。

4_6_3.php

<?php
class Color{
  public $color = null;
  public function __construct(){
    $this->color = 'red';
  }
  public function getColor(){
    return $this->color;
  }
}

define('COLOR1', 'Color');
$Color = new COLOR1();
echo $Color->getColor();

出力結果

>php 4_6_3.php
Fatal error: Class 'COLOR1' not found in E:\xampp\htdocs\Dropbox\技術メモ\php\技術者認定コラム\第四回\source\4_6_3.php on line 13

一方、定数に関数名を格納しておいて呼び出すことはできません。

継承

オブジェクト指向言語では、良く使われる継承についても見ておきましょう。

PHPでは、継承は4_7.phpの例のように書きます。extendsのキーワードを付けてクラスを指定することで、親クラスの内容を引き継いでいます。

4_7.php

<?php
class Animal{
  protected $name = null;
  public function __construct($name){
    $this->name = $name;
  }
  public function getName(){
    return $this->name;
  }
}
class AnimalKind extends Animal{
  private $animalKind = null;
  public function setAnimalKind($animalKind){
    $this->animalKind = $animalKind;
  }
  public function getAnimalKind(){
    return isset($this->animalKind) ? $this->animalKind : false;
  }
}

$Animal = new AnimalKind('ぺちぞー');
$Animal->setAnimalKind('像?');
echo '動物の名前:'.$Animal->getName(), PHP_EOL;
echo '動物の種類:'.$Animal->getAnimalKind(), PHP_EOL;

出力結果

>php 4_7.php
動物の名前:ぺちぞー
動物の種類:像?

PHP技術者認定試験では、継承クラスがどのような振る舞いをするかを問われる問題があります。

  • get_class
  • get_class_methods
  • get_parent_class

などの関数で、どのクラス、メソッドを参照しているかを確認します。

4_8.php

<?php
class HogeClass{
  protected $hoge = null;
  public function __construct($hoge){
    $this->hoge = $hoge;
  }
  public function functionA(){}
  public function functionB(){}
}
Class FugaClass extends HogeClass{
  public function functionC(){}
  public function functionD(){}
}
Class PiyoClass extends FugaClass{
  public function functionE(){}
  public function functionF(){}
}

$class1 = new HogeClass('てすと');
echo 'class1=>クラス:'.get_class($class1).PHP_EOL;
foreach(get_class_methods($class1) as $method){
  echo 'class1=>メソッド:'.$method.PHP_EOL;
}
echo PHP_EOL;

$method = null;
$class2 = new FugaClass('てすと');
echo 'class2=>クラス:'.get_class($class2).PHP_EOL;
echo 'class2=>親クラス:'.get_parent_class($class2).PHP_EOL;
foreach(get_class_methods($class2) as $method){
  echo 'class2=>メソッド:'.$method.PHP_EOL;
}
echo PHP_EOL;

$method = null;
$class3 = new PiyoClass('てすと');
echo 'class3=>クラス:'.get_class($class3).PHP_EOL;
echo 'class3=>親クラス:'.get_parent_class($class3).PHP_EOL;
foreach(get_class_methods($class3) as $method){
  echo 'class3=>メソッド:'.$method.PHP_EOL;
}
echo PHP_EOL;

出力結果

>php 4_8.php
class1=>クラス:HogeClass
class1=>メソッド:__construct
class1=>メソッド:functionA
class1=>メソッド:functionB

class2=>クラス:FugaClass
class2=>親クラス:HogeClass
class2=>メソッド:functionC
class2=>メソッド:functionD
class2=>メソッド:__construct
class2=>メソッド:functionA
class2=>メソッド:functionB

class3=>クラス:PiyoClass
class3=>親クラス:FugaClass
class3=>メソッド:functionE
class3=>メソッド:functionF
class3=>メソッド:functionC
class3=>メソッド:functionD
class3=>メソッド:__construct
class3=>メソッド:functionA
class3=>メソッド:functionB

上記の長いサンプルを見ると、get_classは自分のクラス名を、get_parent_classは一つ上の継承元のクラスを、そしてget_class_methodsでは自分と継承元のクラス全てのメソッドを取得していることがわかります。

この辺りは、フレームワークを自作していたり、プラグインを作ったりしている方ならともかく、普段あまり使わない関数なので忘れがちがと思います。しかし、このように継承されたクラスがどのように振る舞うかは、理解しておく必要があります。

また、以下のように複数のクラスを継承すること(多重継承とも言います)はPHPではできません。

class subClass extends classA,classB{}

複数のクラスを継承したいような場合には、代わりにインターフェースを活用する方法がありますが、ここでは割愛します。

オブジェクトの扱い方や参照渡しは、他の言語で慣れている方であれば、あまり難しくないかもしれません。しかし、PHP独自の動きをする部分もあるため、PHP技術者試験では細かい言語仕様を把握していないと解けない問題もありますの。しっかりと見ておきましょう。

次回は「コンストラクタとデスクトラクタ」についてお話ししていきます。
ではまた。

【参考文献】
「PHPマニュアル」(アクセス:http://php.net/manual/ja/

著者
原田 裕介(はらだゆうすけ)
株式会社ユーザーローカル
東京都在住。携帯のホームページ作成サービスでHTMLのコーディングを始めて、PHPerとなる。
株式会社ハッシュシステム代表取締役やtetolの立ち上げ、株式会社イードでニュースメディアの開発やエンジニア採用を経て、現在はアクセス解析ツールの開発を行いながら、個人でもWEBサービスの開発を行っている。PHP技術者認定上級試験の認定者でもあり、受賞歴はmixi scrap challenge優勝など。

 

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています