JavaScriptばっかり書いてるとPHPを忘れそうなので、既に解説した分をPHP5で書いてみた。
Iterator。楽をしようと思ったら言語組み込みのinterfaceを実装するべし。
<?php
class BookShelf implements IteratorAggregate {
private $books = array();
public function __construct($bookList) {
$this->books = $bookList;
}
public function getIterator() {
return new BookShelfIterator($this->books);
}
}
class BookShelfIterator implements Iterator {
private $books = array();
public function __construct($target) {
$this->books = $target;
}
public function rewind() {
reset($this->books);
}
public function current() {
$book = current($this->books);
return $book;
}
public function key() {
$key = key($this->books);
return $key;
}
public function next() {
$book = next($this->books);
return $book;
}
public function valid() {
$isExisting = $this->current() !== FALSE; // return TRUE or FALSE
return $isExisting;
}
}
class Demo {
public static function main() {
$shelf = new BookShelf(array("空ノ鐘の響く惑星で", "半分の月がのぼる空", "君の嘘、伝説の君"));
// 超ラクチンなイタレーション
// IteratorAggregate を実装しているので foreach を使うと自動的にIteratorの生成から何からしてくれる
foreach ($shelf as $key => $title) {
print $key . ". 『" . $title . "』\n";
}
}
}
Demo::main();
// Result:
// 0. 『空ノ鐘の響く惑星で』
// 1. 『半分の月がのぼる空』
// 2. 『君の嘘、伝説の君』
?>
デモコードに書いたとおり、foreachで回せるようになるので連想配列では特に便利だ。
次、Factory。
<?php
class Factory {
public function __construct() {
}
public function create() {
return new Item();
}
}
class Item {
private $name = "";
public function __construct () {
}
public function setName($newName) {
$this->name = $newName;
}
}
class Demo {
public static function main () {
$fact = new Factory();
$item1 = $fact->create();
$item1->setName("Item1");
$item2 = $fact->create();
$item2->setName("Item2");
}
}
Demo::main();
?>
考えてみれば、ホントはFactoryとItemをabstractにして、実装したクラスは別に用意した方が良かったのかも。
Singleton。PHP5にはアクセス制限があるので言語レベルでの同一性が保証される。
<?php
class Earth {
private static $instance = NULL;
public static function getInstance() {
if (self::$instance == NULL) {
self::$instance = new Earth(); // クラス内なのでコンストラクタを呼び出せる
}
return self::$instance;
}
private $population = 2;
private function __construct() {
// コンストラクタが private なのでクラス外で new されるとエラーになる
}
public function increasePopulation() {
$this->population = $this->population * 2;
}
public function getPopulation() {
return $this->population;
}
}
class Demo {
public static function main() {
$e1 = Earth::getInstance();
print "1st test: " . $e1->getPopulation() . "(e1)\n";
$e2 = Earth::getInstance();
$e2->increasePopulation();
print "2nd test: " . $e2->getPopulation() . "(e2)\n";
print "3rd test: " . $e1->getPopulation() . "(e1)\n";
// 試しに new してみる
print "Additional test: ";
$e3 = new Earth();
}
}
Demo::main();
// Result:
// 1st test: 2(e1)
// 2nd test: 4(e2)
// 3rd test: 4(e1)
// Additional test:
// Fatal error: Call to private Earth::__construct() form context 'Demo'...
?>
コンストラクタがprivateになっているため、クラス外部でnewしてインスタンスを作ろうとすると必ずエラーになる。これにより、Earthクラスのインスタンスを得るにはstaticなgetInstance()メソッドを用いなければならない。
長くなってきたので1度分割しよう。それにしても、クラスベースの言語だと楽だわぁ。メソッド呼び出しが->なのが少し面倒だけれど。
http://yudai.arielworks.com/memo/2005/02/25/215243.trackback
末尾に「3 + 6」の計算結果を繋げて下さい。例えば計算結果が「17」の場合、「215243.trackback17」です。これは機械的なトラックバックスパムを防止するための措置です。