PHP面向对象的那些事儿

2022-12-27 16:23:49 浏览数 (1)

PHP的面向对象在进入5版本后得到了加强,很多好用的特性都得到了支持。下面总结了一些开发时用到的简单的概念,希望对你有帮助

继承关系

面向对象里说的最多的就是继承了吧!

最简单的关系就是a继承b,b又继承c,c继续继承d,是不是很像愚公移山啊!

愚公移山仅仅指的是子子孙孙,而继承关系远没有那么简单,因为愚公还有外甥和侄子呢!


接口和抽象类

接口和抽象类在我看来,其最终的目的都是为了解耦,听起来就很晕吧?其实仔细想想,并没有那么可怕!

接口

顾名思义,接口规范了行为,封装了功能。想想生活中常见的三口插座,他的功能是供电和能够被三口插头。请注意我加粗的动词,如果把三口插座实现为一个类,那么按照传统的做法,在类里面可能会有两个方法:

代码语言:javascript复制
public function powerSuply($voltage){
    //传入电压或国家名
}
public function plugin($sockets){
    //传入插座口数
}

在考虑一下,如果又来个2口插座,美国插座,非洲插座,200口插座,那么在考虑规范和功能的时候就可以考虑把这两个方法抽象出来做成接口形式,只要你送来的东西有这两个方法,那么我就能够调用你,多方便啊!

需要注意的是:

  • 接口使用interface定义
  • 接口中定义的方法必须是public属性(接口就是被人“插”的,隐藏起来怎么用啊?)
  • 接口可以被继承extends
  • 接口中不能实现方法更不能实例化
  • 可以定义方法需要的参数
  • 不能定义变量或静态常量
  • 可以在接口中定义常量const,但是不能被子类或子接口修改。子类调用方法:Interface::CONSTVAR;
  • 更NB的是接口可以多重继承(方法多了注意不要重名)
  • 子类使用implements实现接口中所有方法,属性不变

抽象类

和接口很像,抽象类几乎能实现所有接口能做的事情!

先看看特点吧:

  • 抽象类使用abstract class定义
  • 抽象类中可以不实现方法,需将方法加上abstract属性,也可以实现方法,如__construct
  • 抽象类中方法的属性不限制,但是实例化的子类中方法属性必须更开放(如果原方法是public,继承后不能改为protected)
  • 子类使用extends继承抽象类,并需要实现所有抽象方法
  • 其他特性基本与接口相同
  • 抽象类不能实例化,但是静态方法还是可以直接调用的

区别

  • 接口与抽象类最大的区别就是多重继承了,某个类只能继承一个抽象类
  • 接口只能定义方法,不能实现方法,抽象类则没有限制
  • 方法属性不同,继承方法不同

权衡

之前见过一个帖子说,既然抽象类这么厉害,能够实现接口的所有功能,接口的存在是为什么?

其实根据二者的特点,就可以简单的总结出二者的优劣: 抽象类功能强大,但只能单一继承,没有接口灵活。

所以如果你要抽象一个实体,那么就用抽象类;如果你要抽象一动作,那就用接口!

判断实例

在框架开发中,为了使程序更加健壮,很需要对类的继承情况做限制,比如限制数据库驱动类必须继承于DB类等。

instanceof

代码语言:javascript复制
$a instanceof db

这行代码就是检验$a是否是一个特定的类或者继承于某个类,如果是,就会返回true。

通过实验,普通继承、接口、抽象类都可以用这个方法判断,包括多重继承也可以!

get_class

get_class接收一个实例化的类,返回类名。

代码语言:javascript复制
abstract class bar {
    public function __construct()
    {
        var_dump(get_class($this));
        var_dump(get_class());
    }
}
class foo extends bar {
}
class T extends foo
{
}
new T;

get_parent_class

get_parent_class返回最近的继承关系,无视了接口,注意传递的参数为字符串时的返回值

代码语言:javascript复制
abstract class bar {
    public function __construct()
    {
        echo get_parent_class($this);
        echo get_parent_class('foo');
    }
}
class foo extends bar {
}
class T extends foo
{
}
new T;

is_subclass_of ( is_a() )

代码语言:javascript复制
# 如果此对象是该类的子类,则返回 TRUE
bool is_subclass_of ( object $object , string $class_name )

class_exists

检测一个类是否已定义,这个用在__autoload里在合适不过

代码语言:javascript复制
function  __autoload ( $class )
{
    include( $class  .  '.php' );

     // Check to see whether the include declared the class
     if (! class_exists ( $class ,  false )) {
         trigger_error ( "Unable to load class:  $class " ,  E_USER_WARNING );
    }
}

method_exists

代码语言:javascript复制
# 检查类的方法是否存在于指定的 object中。
bool method_exists ( mixed $object , string $method_name )

注意:此方法会无视protected与private属性的方法

其他方法

method_exists、function_exists、is_callable都是一些检测方法,虽然有些抽象,但是适当的使用可以让你的程序更加高效,健壮。

0 人点赞