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

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()。

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

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