php的多继承实现
记得有一道面试题问php是否支持多继承?
答案:不可以,只支持单继承。
如何实现多继承呢?
答案:可以使用 interface 或 trait 实现 。
为什么会想到这个问题,因为想到如果类继承多个接口,然后他们之间还有相同的属性和方法会引用谁的方法或属性,谁又会被覆盖?
总结:
1.使用 interface 声明类不能被实例化,并且属性必须是常量,方法不能有方法体
2.trait 声明的类不能被实例化,由use引入,会覆盖父类的相同属性及方法,如果有多个use,那么按顺序下面的覆盖最上面的相同的属性及方法
接口是什么?
使用接口(interface),可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容。
接口是通过 interface 关键字来定义的,就像定义一个标准的类一样,但其中定义所有的方法都是空的。
接口中定义的所有方法都必须是公有,这是接口的特性。
trait是什么?
看上去既像类又像接口,其实都不是,Trait可以看做类的部分实现,可以混入一个或多个现有的PHP类中,
其作用有两个:表明类可以做什么;提供模块化实现。
Trait是一种代码复用技术,为PHP的单继承限制提供了一套灵活的代码复用机制。
参考文章:
接口:https://www.cnblogs.com/minigrasshopper/p/7754512.html
trait:https://blog.csdn.net/lemony521/article/details/78322652
php接口interface的使用
接口是什么?
使用接口(interface),可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容。
接口是通过 interface 关键字来定义的,就像定义一个标准的类一样,但其中定义所有的方法都是空的。
接口中定义的所有方法都必须是公有,这是接口的特性。
什么时候用接口?
1、定规范,保持统一性;
2、多个平级的类需要去实现同样的方法,只是实现方式不一样
接口使用规范
- 接口不能实例化
- 接口的属性必须是常量
- 接口的方法必须是public【默认public】,且不能有函数体
- 类必须实现接口的所有方法
- 一个类可以同时实现多个接口,用逗号隔开
- 接口可以继承接口【用的少】
interface usb{
const brand = 'siemens'; // 接口的属性必须是常量
public function connect(); // 接口的方法必须是public【默认public】,且不能有函数体
}
// new usb(); // 接口不能实例化
// 类实现接口
class Android implements usb{
public function connect(){ // 类必须实现接口的所有方法
echo '实现接口的connect方法';
}
}
interface usbA{
public function connect();
}
interface usbB{
public function contact();
}
// 类可以同时实现多个接口
class mi implements usbA,usbB{
public function connect(){
}
public function contact(){
}
}
php中trait的使用
1、php中的trait是啥?
看上去既像类又像接口,其实都不是,Trait可以看做类的部分实现,可以混入一个或多个现有的PHP类中,其作用有两个:表明类可以做什么;提供模块化实现。Trait是一种代码复用技术,为PHP的单继承限制提供了一套灵活的代码复用机制。
2、PHP版本要求:
php5.4开始引入trait,其目的就是在于减少代码的重复,增加代码的复用性。
3、trait的使用场景:
试想这样一种情况,当有一个方法需要在很多的类中使用时,该怎么处理?
通常一般的处理方式会是,写一个基础类,在基类中实现这个方法,然后所有类都继承这个基类。
这是一种处理方法,但不是最好的处理方式。通常采用继承的情况是:几个类具有很大的相似性。比如人作为一个基类,学生、工人、等继承“人”这个基类来扩展。
由此,trait的作用就出来了,trait 可以在多个类中使用。
4、trait如何使用:
引用PHP手册中的例子:
例子一
<?php trait ezcReflectionReturnInfo { function getReturnType() { /*1*/ } function getReturnDescription() { /*2*/ } } class ezcReflectionMethod extends ReflectionMethod { use ezcReflectionReturnInfo; /* ... */ } class ezcReflectionFunction extends ReflectionFunction { use ezcReflectionReturnInfo; /* ... */ } ?>
1、先声明一个trait;
2、在类中使用use将该trait引入。
是不是非常简单(手动逃)?需要注意的是trait的优先级。
5、trait的优先级
(敲黑板)从基类继承的成员会被 trait 插入的成员所覆盖。优先顺序是来自当前类的成员覆盖了 trait 的方法,而 trait 则覆盖了被继承的方法。
优先级:自身方法>trait的方法>继承的方法(就是这样子的。)
看例子
<?php trait HelloWorld { public function sayHello() { echo 'Hello World!'; } } class TheWorldIsNotEnough { use HelloWorld; public function sayHello() { echo 'Hello Universe!'; } } $o = new TheWorldIsNotEnough(); $o->sayHello();//输出是 Hello Universe! ?>
还有一点需要注意的是:多个trait的使用。
<?php trait Hello { public function sayHello() { echo 'Hello '; } } trait World { public function sayWorld() { echo 'World'; } } class MyHelloWorld { use Hello, World; public function sayExclamationMark() { echo '!'; } } $o = new MyHelloWorld(); $o->sayHello(); $o->sayWorld(); $o->sayExclamationMark(); ?>
总结:Trait是一种代码复用技术,为PHP的单继承限制提供了一套灵活的代码复用机制。
附:以上是trait的基本使用,其还有几个比较高级的使用注意点,详细的使用方法可以参见PHP手册,这里给出链接:PHP手册中trait的使用!以上内容中的例子都是来自于该手册。
参考:
1. http://php.net/manual/zh/language.oop5.traits.php
2. http://laravelacademy.org/post/4281.html
3. http://www.jianshu.com/p/47f0cdbe9b2c
地 址 :https://www.cnblogs.com/xiaqiuchu/articles/10393021.html
如果对你有帮助,可以点一下 推荐 或者 关注 吗?会让我的分享变得更有动力~
转载时请带上原文链接,谢谢。