php为什么不支持多继承,PHP 多继承方法总结与思考

本文介绍了PHP中接口、多接口继承、trait以及类组合来实现多继承的效果,展示了如何在单继承的语言环境中实现代码复用和不同角色的组合。同时,探讨了接口的作用和使用场景,以及为何在实际开发中可能不常使用多继承。
摘要由CSDN通过智能技术生成

1、继承单接口方式

interface testA{

function echostr();

}

interface testB extends testA{

function dancing($name);

}

class testC implements testB{

function echostr(){

echo "接口继承,要实现所有相关抽象方法!";

echo "
";

}

function dancing($name){

echo $name."正在跳舞!";

}

}

$demo=new testC();

$demo->echostr();

$demo->dancing("模特");

//运行结果

/**

接口继承,要实现所有相关抽象方法

模特正在跳舞!

**/

//还有另外一个例子

interface UserInterface{ //定义User的接口

function getname();

}

interface TeacherInterface{ //teacher相关接口

function getLengthOfService();

}

class User implements UserInterface { //实现UserInterface接口

private $name = "tom";

public function getName(){

return $this->name;

}

}

class Teacher implements TeacherInterface { //实现TeacherInterface接口

private $lengthOfService = 5; // 工龄

public function getLengthOfService(){

return $this->lengthOfService;

}

}

// 继承自User类,同时实现了TeacherInterface接口.

class GraduateStudent extends User implements TeacherInterface {

private $teacher ;

public function __construct(){

$this->teacher = new Teacher();

}

public function getLengthOfService(){

return $this->teacher->getLengthOfService();

}

}

class Act{

//注意这里的类型提示改成了接口类型

public static function getUserName(UserInterface $_user){

echo "Name is " . $_user->getName() ."
";

}

//这里的类型提示改成了TeacherInterface类型.

public static function getLengthOfService(TeacherInterface $_teacher){

echo "Age is " .$_teacher->getLengthOfService() ."
";

}

}

$graduateStudent = new GraduateStudent();

Act::getUserName($graduateStudent);

Act::getLengthOfService($graduateStudent);

//结果正如我们所要的,实现了有多重身份的一个对象.

2、继承多接口方式

interface testA{

function echostr();

}

interface testB{

function dancing($name);

}

interface testC extends testA,testB{

function singing($nickname);

}

class testD implements testC{

function echostr(){

echo "接口继承,要实现父接口所有相关方法!";

echo "
";

}

function dancing($name){

echo $name."正在跳舞!";

echo "
";

}

function singing($nickname){

echo $nickname."正在唱歌!";

}

}

$demo=new testD();

$demo->echostr();

$demo->dancing("模特");

$demo->singing("周杰伦");

//运行结果

/**

接口继承,要实现父接口所有相关方法!

模特正在跳舞!

周杰伦正在唱歌!

**/

需要注意的是当你接口继承其它接口时候,直接继承父接口的静态常量属性和抽象方法,所以类实现接口时必须实现所有相关的抽象方法

3、使用trait

自php5.4.0起,php实现了一种代码复用的方法称为trait.

Trait是为类似php的单继承语言所准备的一种代码服用机制。Trait为了减少单继承语言的限制,使开发人员能够自由地在不同层次结构内独立的类复用method. Trait 和Class 组合的语义定义了一种减少复杂性的方式,避免传统的多继承和 Mixin 类相关典型问题。

Trait 和 Class 相似,但仅仅旨在用细粒度和一致的方式来组合功能。 无法通过 trait 自身来实例化。它为传统继承增加了水平特性的组合;也就是说,应用的几个 Class 之间不需要继承。

优先级:从基类继承的成员被 trait 插入的成员所覆盖。优先顺序是来自当前类的成员覆盖了 trait 的方法,而 trait 则覆盖了被继承的方法。

class Base {

public function sayHello() {

echo 'Hello ';

}

}

trait SayWorld {

public function sayHello() {

parent::sayHello();

echo 'World!';

}

}

class MyHelloWorld extends Base {

use SayWorld;

}

$o = new MyHelloWorld();

$o->sayHello();

//通过逗号分隔,在 use 声明列出多个 trait,可以都插入到一个类中。

4、通过组合模拟多重继承

class User {

private $name = "tom";

public function getName(){

return $this->name;

}

}

class Teacher{

private $lengthOfService = 5; // 工龄

public function getLengthOfService(){

return $this->lengthOfService;

}

}

// 上面的类中的set方法就不写了.

// 如果有个研究生,既是学生也算工龄.

class GraduateStudent extends User {

private $teacher ;

public function __construct(){

$this->teacher = new Teacher();

}

public function getLengthOfService(){

return $this->teacher->getLengthOfService();

}

}

$graduateStudent = new GraduateStudent();

echo "name is ".$graduateStudent->getName()."
";

echo "lengthOfService is ".$graduateStudent->getLengthOfService();

5、利用__call & 回调函数实现

其中使用的两个函数可以关注下,然后别忘了,恢复__call默认行为

is_callable

call_user_func_array

class Parent1 {

function method1() {}

function method2() {}

}

class Parent2 {

function method3() {}

function method4() {}

}

class Child {

protected $_parents = array();

public function Child(array $parents=array()) {

$this->_parents = $parents;

}

public function __call($method, $args) {

// 从“父类"中查找方法

foreach ($this->_parents as $p) {

if (is_callable(array($p, $method))) {

return call_user_func_array(array($p, $method), $args);

}

}

// 恢复默认的行为,会引发一个方法不存在的致命错误

return call_user_func_array(array($this, $method), $args);

}

}

$obj = new Child(array(new Parent1(), new Parent2()));

print_r( array($obj) );die;

$obj->method1();

$obj->method3();

补充内容 - 接口

接口是什么?

使用接口(interface),可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容。

接口是通过 interface 关键字来定义的,就像定义一个标准的类一样,但其中定义所有的方法都是空的。

接口中定义的所有方法都必须是公有,这是接口的特性。

什么时候用接口?

1、定规范,保持统一性;

2、多个平级的类需要去实现同样的方法,只是实现方式不一样

接口使用规范

接口不能实例化

接口的属性必须是常量

接口的方法必须是public【默认public】,且不能有函数体

类必须实现接口的所有方法

一个类可以同时实现多个接口,用逗号隔开

接口可以继承接口【用的少】

思考问题:

所以,我们到底为什么要使用多继承?

emmm,这是个好问题,因为我没有答案,当然可能是我还没有遇到过必须使用多继承的场景。

不过就目前见识来看,接口,抽象类已经很足够使用了,所以私以为,可能多继承主要应用场景是一些遗留问题吧?欢迎看官指正了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值