php基础2(继承,接口)
1.了解PHP的继承特性
在PHP中,类继承通过extends关键字实现。
<?php
// Define a base Employee class
class Employee {
private $name;
// Define a setter for the private $name member.
function setName($name) {
if ($name == "") echo "Name cannot be blank!";
else $this->name = $name;
}
// Define a getter for the private $name member
function getName() {
return "My name is ".$this->name."<br />";
}
} //end Employee class
// Define an Executive class that inherits Employee
class Executive extends Employee {
// Define a method unique to Employee
function pillageCompany() {
echo "I'm selling company assets to finance my yacht!";
}
} //end Executive class
// Create a new Executive object
$exec = new Executive();
// Call the setName() method, defined in the Employee class
$exec->setName("Richard");
// Call the getName() method
echo $exec->getName();
// Call the pillageCompany() method
$exec->pillageCompany();
?>
输出:My name is Richard
I'm selling company assets to finance my yacht!
因为所有员工都有姓名,所以Executive类继承了Employee类,避免了必须重新创建name成员及相应获取方法和设置方法的麻烦。
2.php构造函数的继承问题
构造函数的继承节省的是代码的重写,而不是方法的声明,也就是说,在父类中声明的构造函数必须再在子类中声明一次,其实,这也是一个重写的过程。
PHP的构造函数继承必须满足以下条件:
- 当父类有构造函数的声明时,子类也必须有声明,否则会出错。
- 在执行父类的构造函数时,必须在子类中引用parent关键字。
如果父类有构造函数,而且子类没有构造函数,那么在子类实例化时确实会执行父类构造函数。例如,假设Employee类有如下构造函数:
<?php
class Fruit {
public function __construct($name)
{
echo '水果'.$name.'创建了';
}
}
class Apple extends Fruit {
public function __construct($name)
{
parent::__construct($name);
}
}
$apple = new Apple("苹果");
// 输出 水果苹果创建了
?>
如果父类有构造函数,而且子类没有构造函数,那么在子类实例化时确实会执行父类构造函数。例如,假设Employee类有如下构造函数:
function __construct($name){
$this->setName($name);
}
然后实例化CEO类,获得其name成员:
$ceo= new CEO("Gonn");
echo $ceo->getName();
结果:
$ceo= new CEO("Gonn");
echo $ceo->getName();
但是,如果子类也有构造函数,那么当子类实例化时,不论父类是否有构造函数,都会执行子类自己的构造函数。例如,假设除了Employee类包含上述构造函数外,CEO类也包含如下构造函数:
function __construct(){
echo "CEO object created!";
}
再来实例化CEO类,以同样的方式执行getName(),这次将得到不同的输出:
CEO object created!
My name is Gonn
当遇到parent::__construct()时,PHP开始沿着父类向上搜索合适的构造函数。因为在Executive中没有找到,所以继续搜索知道Employee类,在这里找到了合适的构造函数。如果PHP在Employee类中找到构造函数,就会执行这个构造函数。如果希望既执行Employee构造函数,又执行Executive构造函数,则需要在Executive构造函数中调用parent::__construct()。
此外,还可以选择另一种方式来引用父类的构造函数。例如,假设创建新的CEO对象时,Employee和Executive的构造函数都要执行。如上述,可以在CEO的构造函数中显示地引用这些构造函数,如下:
function __construct($name){
Employee::__constrcut($name);
Executive::__construct();
echo "CEO object created!";
}
3.PHP接口的介绍与实现
接口定义了实现某种服务的一般规范,声明了所需的函数和常量,但不指定如何实现。之所以不给出实现的细节,是因为不同的实体可能需要用不同的方式来实现公共的方法定义。
接口中不定义类成员!类成员的定义完全交给实现类来完成。
<?php interface Fruit
{ const MAX_WEIGHT = 5; //此处不用声明,就是一个静态常量
function setName($name);
function getName();
} //实现接口
class Apple implements Fruit {
private $name;
function getName() {
return $this->name;
}
function setName($_name) {
$this->name = $_name;
}
}
$apple = new Apple(); //创建对象
$apple->setName("苹果");
echo "创建了一个" . $apple->getName();
echo "<br />";
echo "MAX_GRADE is " . Apple::MAX_WEIGHT; //静态常量
?>
当类通过implements关键字实现了接口后,就完成了一个契约。接口中的所有方法都必须实现,倘若实现类没有实现所有的方法,则必须声明为抽象类,否则将出现下面所示的致命错误:
PHP还可以实现多个接口,一个类可以实现多个接口。只要使用 ‘,’ 将多个接口链接起来就可以。
<?php
interface Fruit
{
const MAX_WEIGHT = 5; //此处不用声明,就是一个静态常量
function setName($name);
function getName();
}
interface Food {
function dilicious();
}
//实现接口
class Apple implements Fruit, Food {
private $name;
function getName() {
return $this->name;
}
function setName($_name) {
$this->name = $_name;
} function dilicious() {
echo '好吃';
}
}
$apple = new Apple(); //创建对象
$apple->setName("苹果");
echo "创建了一个" . $apple->getName();
echo $apple->dilicious();
echo "<br />";
echo "MAX_WEIGHT is " . Apple::MAX_WEIGHT; //静态常量
?>
PHP还可以继承并实现接口:
interface Fruit {
const MAX_WEIGHT = 5; //此处不用声明,就是一个静态常量
function setName($name);
function getName();
}
interface Food {
function dilicious();
}
class FoodObjects { }
//实现接口
class Apple extends FoodObjects implements Fruit, Food {
private $name;
function getName() {
return $this->name;
}
function setName($_name) {
$this->name = $_name;
}
function dilicious() {
echo '好吃';
}
}