PHP学习之类与对象(三)
抽象类
- 定义为抽象的类不能被实例化;
- 任何一个类,如果它里面至少有一个方法是被声明为抽象的,那么这个类就必须被声明为抽象的;
- 被定义为抽象的方法只是声明了其调用方式(参数),不能定义其具体的功能实现;
- 继承一个抽象类时,子类必须定义父类中的所有抽象方法;另外,这些方法的访问控制(public/protected/private)必须和父类中一样(或者更为宽松)。例如某个抽象方法被声明为受保护的,那么子类中实现的方法就应该声明为受保护的或者公有的,而不能定义为私有的。
- 此外方法的调用方式必须匹配,即类型和所需参数数量必须一致。例如,子类定义了一个可选参数,而父类抽象方法的声明里没有,则两者的声明并无冲突。 这也适用于 PHP 5.4 起的构造函数。在 PHP 5.4 之前的构造函数声明可以不一样的。
对象接口
- 使用接口(interface),可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容。
- 接口是通过 interface 关键字来定义的,就像定义一个标准的类一样,但其中定义所有的方法都是空的。
- 接口中定义的所有方法都必须是公有,这是接口的特性。
接口的实现(implements)
- 要实现一个接口,使用 implements 操作符。
- 类中必须实现接口中定义的所有方法,否则会报一个致命错误。
- 类可以实现多个接口,用逗号来分隔多个接口的名称。
- 实现多个接口时,接口中的方法不能有重名。
- 接口也可以继承,通过使用 extends 操作符。
- 类要实现接口,必须使用和接口中所定义的方法完全一致的方式。否则会导致致命错误。
- 接口中也可以定义常量。接口常量和类常量的使用完全相同,但是不能被子类或子接口所覆盖。
Trait
一个类可以组合多个Trait,通过逗号相隔,如use trait1,trait2
header("Content-type: text/html; charset=utf-8");
//使用trait关键字声明一个trait Dog,注意trait不能像类一样实例化
trait trait1{
public function eat(){
echo "This is trait1 eat!" . "<br/>\n";
}
public function drive(){
echo "This is trait1 drive!" . "<br/>\n";
}
}
trait trait2{
public function eat(){
echo "This is trait2 eat!" . "<br/>\n";
}
public function drive(){
echo "This is trait2 drive!" . "<br/>\n";
}
}
class cat{
use trait1, trait2{
//使用insteadof将trait1中的eat,drive方法分别替代trait2中的同名方法
trait1::eat insteadof trait2;
trait1::drive insteadof trait2;
}
}
class dog{
use trait1, trait2{
//使用insteadof将trait1中的eat,drive方法分别替代trait2中的同名方法
trait1::eat insteadof trait2;
trait1::drive insteadof trait2;
//使用as将trait2中同名方法eat和drive分别起别名为eaten和driven
trait2::eat as eaten;
trait2::drive as driven;
}
}
$cat = new cat();
$cat -> eat();//This is trait1 eat!
$cat -> drive();//This is trait1 drive!
$dog = new dog();
$dog -> eat();//This is trait1 eat!
$dog -> drive();//This is trait1 drive!
$dog -> eaten();//This is trait2 eat!
$dog -> driven();//This is trait2 drive!
?>
<?php
header("Content-type: text/html; charset=utf-8");
trait Cat{
public function eat(){
echo "This is Cat eat!". "<br/>\n";
}
}
trait Dog{
use Cat;
public function drive(){
echo "This is Dog drive!". "<br/>\n";
}
//定义抽象方法getName(必须在子类中实例化)
abstract public function getName();
public function test(){
static $num = 0;
$num ++;
echo $num . "<br/>\n";
}
//定义trait Dog的静态方法say
public static function say(){
echo "This is dog say!". "<br/>\n";
}
}
class animal{
use Dog;
public function getName(){
echo "This is animal name!". "<br/>\n";
}
}
$animal = new animal ();
$animal -> getName();//This is animal name!
$animal ->eat();//This is Cat eat!
$animal -> drive();//This is Dog drive!
$animal::say();//调用静态方法,This is dog say!
$animal -> test();//1
$animal -> test();//2
?>
匿名类
interface SomeInterface {}
trait SomeTrait {}
//使用new class来创建匿名类
var_dump(new class(10) extends SomeClass implements SomeInterface {
private $num;
public function __construct($num)
{
$this->num = $num;
}
use SomeTrait
header("Content-type: text/html; charset=utf-8");
class Outer{
private $prop = 1;
protected $prop2 = 2;
protected function func1(){
return 3;
}
public function func2(){
return new class($this ->prop) extends Outer{
private $prop3;
public function __construct($prop){
$this -> prop3 = $prop;
}
public function func3(){
return $this -> prop2 + $this -> prop3 + $this->func1();
}
};
}
}
echo (new Outer) -> func2() -> func3();//6
?>
<?php
function anonymous_class()
{
return new class {};
}
if (get_class(anonymous_class()) === get_class(anonymous_class())) {
echo 'same class';
} else {
echo 'different class';
}
echo get_class(new class {});