显示标签为“oop”的博文。显示所有博文
显示标签为“oop”的博文。显示所有博文

2009年1月19日星期一

SPL DirectoryIterator

DirectoryIterator 提供目录迭代功能。可替换 opendir() 和 dir 伪类功能。

opendir() 写法:
$path = '.';
if (is_dir($path)) {
if ($dh = opendir($path)) {
while (false !== ($file = readdir($dh))) {
echo "filename: $file \tfiletype: ", filetype($path . $file), "\n";
}
closedir($dh);
}
}


dir 伪类写法:
$path = '.';
$dir = dir($path);
while (false !== ($entry = $dir->read())) {
echo $entry, "\n";
}
$dir->close();


主角出场:
$path = '.';
$dir = new DirectoryIterator($path);
foreach ($dir as $fileinfo) {
echo 'filename:', $fileinfo->getFilename(), "\tfiletype:", $fileinfo->getType(), "\n";
}


参考资料:
http://www.php.net/manual/en/class.directoryiterator.php
http://www.php.net/manual/en/class.splfileinfo.php
http://www.php.net/~helly/php/ext/spl/

2009年1月8日星期四

SPL File Object

class SplFileObject extends SplFileInfo implements RecursiveIterator, SeekableIterator
SPL 文件对象继承自 SplFileInfo, 实现了 RecursiveIterator, SeekableIterator 接口。

一般我们访问文件方式:

$filename = '/path/ to/file';
$fp = fopen($filename, 'r');
if ($fp) {
while (!feof($fp)) {
$text = fgets($fp);
echo $text;
}
fclose($fp);
}


利用 SplFileObject 我们可以这么写:

$filename = '/path/ to/file';
$file = new SplFileObject($filename);
$file->openFile();
foreach ($file as $line) {
echo $line;
}

因为 SplFileObject 实现了RecursiveIterator 迭代器接口, foreach 可以很方便的访问到它。

写文件:

$filename = '/path/to/file';
$file = new SplFileObject($filename);
$file->openFile('w');
$file->fwrite('some text');


继承自 SplFileInfo 的一些方法:

echo '修改时间:', $file->getMTime(), "\n";
echo '所在路径:', $file->getPath(), "\n";
echo '文件名:', $file->getFilename(), "\n";
echo '全路径(路径+文件名):', $file->getPathname(), "\n";



更多方法请参考 Spl 文档

2007年7月9日星期一

Observer pattern

观察者模式 Observer Pattern


观察者模式为您提供了避免组件之间紧密耦合的另一种方法。该模式非常简单:一个对象通过添加一个方法(该方法允许另一个对象,即观察者 注册自己)使本身变得可观察。当可观察的对象更改时,它会将消息发送到已注册的观察者。这些观察者使用该信息执行的操作与可观察的对象无关。结果是对象可以相互对话,而不必了解原因。



SPL 提供的 Observer 接口:
观察者:
SplObserver::update(SplSubject $subject)
观察者接口,由被观察对象调用。

主题(被观察者):
SplSubject::attach(SplObserver $observer)
参数:
$observer 要添加的观察者

SplSubject::detach(SplObserver $observer)
参数:
$observer 要删除的观察者

SplSubject::notify()
通知所有观察者.

2007年4月21日星期六

概念: interface 和 abstract class 的区别

什么是 abstract class
PHP 5 引入抽象类和方法。抽象类不能被实例化。任何类只要包含有抽象方法(即使只有一个抽象方法)就必须也被定义为抽象。定义为抽象的方法只需要简单的声明而不用实现。
从抽象类继承的时候,所有父类中标记为抽象方法的声明都必须在子类中定义;此外,这些方法还必须用相同的(或更弱的)访问控制。比如,如果抽象方法定义为保护(protected),函数实现必须被定义为protected或者public

抽象类例子:
abstract class AbstractClass
{
// Force Extending class to define this method
abstract protected function getValue();
abstract protected function prefixValue($prefix);

// Common method
public function printOut() {
print $this->getValue() . "\n";
}
}

class ConcreteClass1 extends AbstractClass
{
protected function getValue() {
return "ConcreteClass1";
}

public function prefixValue($prefix) {
return "{$prefix}ConcreteClass1";
}
}

class ConcreteClass2 extends AbstractClass
{
public function getValue() {
return "ConcreteClass2";
}

public function prefixValue($prefix) {
return "{$prefix}ConcreteClass2";
}
}

$class1 = new ConcreteClass1;
$class1->printOut();
echo $class1->prefixValue('FOO_') ."\n";

$class2 = new ConcreteClass2;
$class2->printOut();
echo $class2->prefixValue('FOO_') ."\n";



什么是 interface
Object Interface 对象接口允许你创建这种代码,一个类必须实现的指定方法,而又不必定义这些方法如何处理。接口使用interface关键字定义,和标准类定义一样,但是任何方法都没有内容。接口内所有的方法声明都必须为公开(public),这是接口的本质(呵呵,所谓接口嘛,就是用于交互的)。
实现
要实现一个接口,使用 implements 操作符。接口中的所有方法都必须在一个类中实现;不这么做会导致一个致命错误(fatal error)。 如果想要的话,使用逗号分隔每个接口,一个类可以实现多个接口。
注意:一个类不能实现两个有同样函数名的接口,因为这导致这个函数的含义模糊。

接口的例子:
// Declare the interface 'iTemplate'
interface iTemplate
{
public function setVariable($name, $var);
public function getHtml($template);
}

// Implement the interface
// This will work
class Template implements iTemplate
{
private $vars = array();

public function setVariable($name, $var)
{
$this->vars[$name] = $var;
}

public function getHtml($template)
{
foreach($this->vars as $name => $value) {
$template = str_replace('{' . $name . '}', $value, $template);
}

return $template;
}
}

// This will not work
// Fatal error: Class BadTemplate contains 1 abstract methods
// and must therefore be declared abstract (iTemplate::getHtml)
class BadTemplate implements iTemplate
{
private $vars = array();

public function setVariable($name, $var)
{
$this->vars[$name] = $var;
}
}


实现多个接口:
class MyClass implements anInterface, anotherInterface {
//...
}


如果想要继承一个类并实现一个接口,先使用“extends”然后“implements”:
class MyChildClass extends MyParentClass implements MyInterface
{
// definition
}



interface 和 abstract class 的区别
PHP 5 中类没有多重继承,但可以实现多个接口。这应该是接口的主要用途。这点和Java类似,和C++不同。应该是学java,对多重继承的一种解决方式吧。

代码形式上来说,接口只是一个声明,其方法没有任何实现代码;抽象类的方法既可以没有实现代码,也可以拥有实现代码。

2007年3月18日星期日

概念: 构造函数和析构函数

构造函数和析构函数
构造函数
void __construct ( [mixed args [, ...]] )

PHP 5 允行开发者在一个类中定义一个方法作为构造函数。具有构造函数的类会在每次创建对象时先调用此方法,所以非常适合在使用对象之前做一些初始化工作。

注: 如果子类中定义了构造函数则不会暗中调用其父类的构造函数。要执行父类的构造函数,需要在子类的构造函数中调用 parent::__construct()。

例子 19-6. 使用新标准的构造函数
<?php
class BaseClass {
function __construct() {
print "In BaseClass constructor\n";
}
}

class SubClass extends BaseClass {
function __construct() {
parent::__construct();
print "In SubClass constructor\n";
}
}

$obj = new BaseClass();
$obj = new SubClass();
?>


为了实现向后兼容性,如果 PHP 5 在类中找不到 __construct() 函数,它就会尝试寻找旧式的构造函数,也就是和类同名的函数。因此唯一会产生兼容性问题的情况是:类中已有一个名为 __construct() 的方法,但它却又不是构造函数。
析构函数
void __destruct ( void )

PHP 5 引入了析构函数的概念,这类似于其它面向对象的语言,如 C++。析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行。

例子 19-7. 析构函数示例
<?php
class MyDestructableClass {
function __construct() {
print "In constructor\n";
$this->name = "MyDestructableClass";
}

function __destruct() {
print "Destroying " . $this->name . "\n";
}
}

$obj = new MyDestructableClass();
?>


和构造函数一样,父类的析构函数不会被引擎暗中调用。要执行父类的析构函数,必须在子类的析构函数体中显式调用 parent::__destruct()。

注: 析构函数在脚本关闭时调用,此时所有的头信息已经发出。

注: 试图在析构函数中抛出一个异常会导致致命错误。