复习PHP-语言参考-类与对象

1.简介

没啥说的。

2.基本概念

类有自己的属性和方法,内部使用可用伪变量$this(是该类的一个引用)访问属性或方法

类通过new被实例化(如果该类属于某个命名空间,则需要写全)

可以通过clone 复制一个新实例

类可以被继承extends,接口类interface可以被implements继承

5.5起,可以直接输出类的完全限定名称Classname::class 将输出 namespace\classname

5.3引入的新实例化类的方法

class T

{

     static public function getT()

    {

          return new static;

    }

}

只知道可以这样实例化,但不知道有什么区别。

例:PHP的单例模式

 

<?php
/**
* 演示一个单例模式
* 既然是单例,则他不应该被继承,不能被多次实例化
* @author Lou
* */
final class T //不能被继承
{
    private static $ins = null; //我就是唯一的实例
    public $num = 0; //num做校对用
    private function __construct() //保证不能被外部访问到
    {
        $this->num = mt_rand(10000, 99999); //随机一个num
    }
    private function __clone()
    {
        return false; //不允许被克隆
    }
    public static function creatIns()
    {
        if(self::$ins == null) //如果是null
        {
            self::$ins = new self(); //就实例化
        }
        return self::$ins; //否则直接返回
    }
}

?>

3.类属性

以public protected private开头

5.3以后,可以使用nowdocs格式声明类属性

可用static修饰类属性

4.类常量

用const修饰 且接一个无$符号的格式常量名

5.自动加载类

x.spl_auto_register的用法(注册自定义加载文件的函数来实现自动加载类文件)

<?php
function loader($classname)
{
    $filename = "class/".$classname.".class.php";
    if(is_file($filename))
    {
        require_once $filename;
    }else{
        exit("can not find file");
    }
}
spl_autoload_register("loader");
$obj = new A;
echo $obj->a;
?>

提示:可以注册多个自定义加载文件的函数,用于包含不同的类文件目录

6.构造函数和析构函数

__construct 类实例创建时调用

__destruct 类实例销毁时调用

7.访问控制

public 外部内部继承都可直接访问

protected 仅内部和继承可以直接访问

private 仅内部可以直接访问

8.继承

extends  可以继承父类的 公有, 受保护,属性和方法

9.范围解析操作符::

可用来访问静态类成员,或者类常量

扩展:self,parent 和 static 这三个特殊的关键字是用于在类定义的内部对其属性或方法进行访问的,还有一个伪变量$this

10.static(静态)关键字

需要注意的是 可以有这种表达式 static::who();//who是类成员

这个表达式的用处在于可以后期静态绑定(就是通过实例化的OBJ来判定这个who是子类的who还是父类的who,如果是子类实例化,则这个who就调用子类的who)

注意:static::只能用于静态属性或方法

11.抽象类

abstract 抽象类不能被实例化,只能被继承。

抽象类的抽象方法必须被子类重写,且重写的控制权限必须大于等于父类的,如父类是protected,子类则必须至少为protected,也可以是public,但不能是private。

提示:子类方法可以有可选参数(抽象父类没有的话)。

12.对象接口

interface  所有的类方法都必须是公有的空方法。子类接口父类用implements,子类必须实现父类所有的方法,子类可以实现多个接口,用,分隔。

接口可以继承别的类

接口里可以有常量成员,但需要注意的是,子类不能复写它。(遵循常量不能修改的特性)

13.traits

这个可以非常方便地使用其他类的东西,而不需要继承或者实例化。它的优先级为:从基类继承的成员被 trait 插入的成员所覆盖。优先顺序是来自当前类的成员覆盖了 trait 的方法,而 trait 则覆盖了被继承的方法。

如何使用? 直接用use。 可以use多个traits,用,分隔即可。

如果一个use的两个traits 有相同的方法怎么办?(即方法同名),这时需要用insteadof 和as 来区别,但应当避免这样。

use A,B {
        B::go insteadof A;//这时B的go方法将会覆盖A的go方法
        A::bed as protected abed; //a的bed方法将会以abed来访问(这样做即可以保留同名的方法又能解决冲突,是个好办法)    }

注意:as语法还可以修改控制级别

如:A::bed as protected abed; 或者仅仅修改它的级别

A::bed as protected; 需要注意的是,他可以破坏trait里的私有为公共,这在某些方面来说好像不肿么好。

trait不能用final修饰,并且不能被继承,好像只能被use。

类能使用trait,trait也能使用trait

trait也可以使用抽象abstract方法,在use的类中必须重写该方法

(需要注意的是:如果trait中的抽象类为私有,则use的类不能重写它,即使将其as成受保护或公有也不行)

trait里同样可以定义属性以及static静态成员

注意trait类属性不能被as和重写,所以trait的属性和类的属性必须不重名。

14.重载

重载的参数不能引用传递

所有重载方法都必须为public

重载属性就是当访问一个对象中不存在的属性时,会自动按__set里的规则添加该属性(相关函数为__set,__get,__isset,__unset)

重载方法就是当访问一个对象中不存在的方法时,会自动调用__call里的东西,如果访问的是一个静态不存在的方法时,会自动调用__callstatic里的东西,这两个魔术方法必须公共,_callstatic必须也为static方法。

15.遍历对象

普通遍历 foreach 即可。

可以通过Iterator接口实现自动义遍历对象,不过有啥用啊? 除了调试没啥用感觉。更多遍历参见SPL扩展。

http://www.php.net/manual/zh/language.oop5.iterations.php

16.魔术方法

__construct(),__destruct(),__call(),__callStatic(),__get(),__set(),__isset(),__unset(),__sleep(),__wakeup(),__toString(),__invoke(),__set_state()和 __clone() 等方法在 PHP 中被称为"魔术方法"(Magic methods)。

__sleep和__wakeup的用法是:

当想序列化一个对象并保存时(serialize和unserialize),这两个方法就会被调用。

__sleep可以返回一个数组(包含只需要序列化的属性),用于清理不想被序列化的属性。

unserialize一个对象时,__wakeup会首先被调用,如重新建数据库连接等。(即一个数据库对象被unserialize时,可以在__wakeup里添加重新调用连接数据库的方法,就可以重新连接了。)

注意:序列化只能序列化类属性,并不能序列化类方法。

感觉序列化对象有点像游戏里的暂停功能。。。

__toString:当你想echo obj时  显示这个(这个方法必须返回一个string用于显示),实际用处也不大吧。

__invoke当尝试将实例化的对象用函数方式调用时,用这个

像这样 $obj(5),变态才会这样调用。

__set_state 注意这个类魔术方法必须是static的,当var_export导出类时,这个方法会被调用

http://www.php.net/manual/zh/language.oop5.magic.php

具体看这里吧,不知道有啥用。

17.final关键字

类的属性不能为final,但类 和类方法可以被定义为final,即不能继承和重写。

18.对象复制

就是 clone,平时用不多,手册上就GTK时会用到,但现目前PHP做界面啊。。。 我也想啊

当被clone时,对象里的__clone会被调用。

比如你可以在__clone里把类属性做一个递增,你就会知道这个对象被克隆了多少次。

18.对象比较

== 同一个类的实例并且属性和属性值相等

=== 必须是同一个类的同一个实例(即同一个对象)。

提示:PHP的扩展中可以自定义对象比较的原则。

19.类型约束

参见 C++的类方法参数类型  如  CLASSA $a 这样子  必须加上参数类型。

http://www.php.net/manual/zh/language.oop5.typehinting.php 其他看这里

20.后期静态绑定

看例子就明白了。

<?php
class A
{
    public static function who()
    {
        echo __CLASS__;
    }
    public static function getWho()
    {
        //echo self::who();
        echo static::who();
    }
}
class B extends A
{
    public static function who()
    {
        echo __CLASS__;
    }
}
$obja = new A;
$obja->getWho();
$objb = new B;
$objb->getWho();
//用self::who()将永远显示A,而用static::who将显示AB
?>

http://www.php.net/manual/zh/language.oop5.late-static-bindings.php 例4需要注意。(static::在self   parent 下的情况)

21.对象和引用

在之前已经研究过了

$a = new A;

$b = $a; //$a,$b都是 new A的引用

$c = &$a; //$c是$a的引用,$a是new A的引用

22.对象序列化

serialize和unserialize,前面理解过了。需要注意的是,unserialize时,需要包含对象所对应的类文件。(即类)

需要理解的是:当序列化和反序列化与spl_autoload_register组合应用时,反序列化时会自动调用注册进去的函数(即include class文件。)

这一章的内容挺多的,具体回忆可以参考

http://www.php.net/manual/zh/language.oop5.php