访问控制
属性和方法的访问控制(可见标识):public
任何地方private
类自身protected
类自身,自子类及自父类
this
this
可以理解为这个类的一个实例
self
self
代表类本身
__construct
实例化时就会自动执行public function __construct() {}
__destruct
当对象对销毁时自动执行public function __destruct(){}
类常量
定义合不可改变
const ONE = 1
const TWO = self::ONE + 1;
可以在类外部调用Class::Two
parent
parent
代表父类public function __construct(){ parent::__construct();}
final
final class Dad(){}
加到类定义前面表示Dad类不想被继承
class Dad(){
final public function run(){} // 加到方法声明前面,表示方法不想被子类重写
}
namespace
namespace
必须放在代码文件的第一行
受命名空间影响的类型:类(包括抽像类,traits)、接口、函数和常量。
当没有使用namespace
关键字指定命名空间时,当前脚本是存在于全局命名空间的。用\
表示。\Class1
类全在指定的命名空间去查找,没找到则抛出错误。
函数与常量,在指定命名空间查找,没找到则到全局命名空间查找
,还没打到则抛错。
函数
ns1\ns2\fn()
常量
define
定义的常量是全局的,不受命名空间影响。const
定义的常量受命名空间影响。
namespace ns1\ns2;
const ONE = 1;
echo ns1\ns2\ONE;
use
导入类
用use
导入命名空间下的类use ns1\ns2\class1;
用as
重命名导入的类use ns1\ns2\class1 as class2;
导入函数
use function ns1\ns2\fn as fn1;
导入常量
use const ns1\ns2\ONE;
自动加载
__autoload
function __autoload($className){ require $className . '.php';}
spl_autoload_register
传匿名函数
spl_autoload_register(function($className){ require $className . '.php'; });
传函数名
function test($className){ require $className . '.php'; }
spl_autoload_register('test');
传类
class Momo
{
function autoload($className)
{
require $className . '.php';
}
}
spl_autoload_register([new Momo, 'autoload']);
static
声明静态属性和静态方法,不经过实例化,通过类名即可调用。
class Person()
{
public static $hand = '手';
public static function run()
{
echo 'running...';
}
}
echo Person::$hand;
Person::run();
类内部调用静态属性和静态方法用self
关键字
echo self::$hand;
self::run();
调用父类的静态属性和静态方法用parent
关键字
echo parent::$hand;
parent::run();
后期静态绑定
class A
{
public static function who()
{
echo 'A类的who方法';
}
public static function test1()
{
self::who();
}
public static function test2()
{
static::who();
}
}
class B extends A
{
public static function who()
{
echo 'B类的who方法';
}
}
B::test1(); // test1内部用的self,调用的是自身(A类)的静态方法
B::test2(); // 后期绑定。内部用static,根据后期的调用环境确定,调用的是B类的静态方法
魔术方法
__set
class Test
{
private $name = '';
public function __set($var, $val)
{
// 对$val进行数据处理
$this->$var = $val;
}
}
$test = new Test();
$test->name = 'tom'; // 赋值tom
__get
class Test
{
private $name = 'jack';
public function __get($var)
{
return $this->$var;
}
}
$test = new Test();
echo $test->name; // jack
__isset
用于检测私有属性是否存在
class Test
{
private $name = 'mary';
public function __isset($var)
{
return isset($this->$var);
}
}
$test = new Test();
var_dump($test->name); // 如果不设置__isset,返回false,设置后返回true
__unset
用于删除私有属性
class Test
{
private $name = 'Levi';
public function __unset($var)
{
unset()
}
}
$test = new Test;
unset($test->name); // 会触发__unset
__call
避免调用一个不存在的方法时产生错误,当调用的方法不存在时,__call
方法会自动调用
class Test
{
public function __call($fn_name, $fn_arguments)
{
echo $fn_name;
print_r($fn_arguments);
}
}
$test = new Test();
$test->go(1, 'ok'); // 自动调用`__call`方法,打印出函数名和参数数组
__callStatic
同__call
类似
避免调用一个不存在的静态方法
class Test
{
public static function __callStatic($fn_name, $fn_arguments)
{
echo $fn_name;
print_r($fn_arguments);
}
}
// `__callStatic` 必须声明为静态方法
Test::go(1, 'ok');
__invoke
当对象以函数的形式调用的时候,自动调用__invoke
方法
class Test
{
public function __invoke($args)
{
return $args;
}
}
$test = new Test();
$test('go.....'); // 运行__invoke
__toString
当打印对象是会调用__toString
方法
class Test
{
public function __toString()
{
return 'Hello world!';
}
}
$test = new Test;
echo $test; // 输出 Hello world!
对象复制
浅拷贝
比较省内存,对象的拷贝默认是浅拷贝。
$a = new Test();
$b = $a; // 浅拷贝。传址。改变$b。$a也会改变。
对象的复制是浅拷贝的。传址。
普通变量的拷贝是深拷贝的。传值。
深拷贝
$a = new Test();
$b = clone $a; // 深拷贝。改变$b,不会改变$a。
__clone
当使用clone
关键字时,自动调用__clone
方法
class Test
{
public $obj = null;
public function __clone()
{
$this->obj = clone $this->obj;
}
}
class Person
{
public $sex = 0;
}
$a = new Test;
$a->obj = new Person;
$b = clone $a; // 触发`__clone` 对obj进行深拷贝
$b->obj->sex = 1; // $b中的obj对象改变了。而$a中的obj对象没变。
类型约束
class A
{
public function go()
{
echo 'go .....';
}
}
function test(A $a) {
$a->go();
}
test(new A());
Trait
单继承语言PHP的代码复用机制。
Trait Bt
{
public function atest()
{
echo 'Hello ';
}
public function btest()
{
echo 'world';
}
public function ab()
{
$this->atest();
$this->btest();
}
}
class Test
{
use Bt; // 使用Bt Trait,便拥有了Bt所有的方法
}
$test = new Test;
$test->ab();
继承多个Trait
Trait A
{
public $name = 'tom';
public function a()
{
echo 'Hello ';
}
}
Trait B
{
public function b()
{
echo 'world ';
}
}
class Test
{
use A,B;
public function c()
{
echo $this->name;
}
}
$test = new Test;
$test->a();
$test->b();
$test->c(); // Hello world tom
Trait 支持嵌套
Trait A{}
Trait B{}
Trait C
{
use A,B;
}
Class Test
{
use C;
}
interface
接口是类的模板。在接口中只定义需要实现的空方法,这些方法在接口中不做具体实现。
接口是不能被实例化的。
Interface Person
{
public function eat();
public function sleep();
}
class man implements Person
{
public function eat()
{
echo 'eating...';
}
public function sleep()
{
echo 'sleeping...';
}
}
class L
{
public static function factory(Person $user) // 用接口作类型约束
{
return $user;
}
}
$user = L::factory(new Man());
$user->eat();
$user->sleep();
接口可以继承接口。
接口可以继承多个接口。
接口可以使用常量,叫接口常量,和类的常量使用方法相同
Interface Ia
{
const ONE = 1;
public function eat();
}
Interface Ib
{
public function sleep();
}
Interface AB extends Ia,Ib
{}
// class Test implements Ia,Ib 类可以同时继承多个接口
class Test implements AB
{
public function eat()
{
echo 'eating...';
}
public function sleep()
{
echo 'sleeping...';
}
}
$test = new Test;
$test->eat();
$test->sleep();
echo Ia::ONE; // 使用接口常量
abstract
抽象类不能被实例化。
如果至少有一个方法被声明为抽象的,那么这个类必须被声明为抽象的。
抽象方法只能声明,不能有具体功能实现。
抽象类可以有被实现的的方法。
继承抽象类,子类必须实现父类中所有的抽象方法。
这些方法的访问控制必须和父类一样,或者更宽松,不能比父类更严格。
方法的调用方式也必须匹配。类型和参数数量必须一致,但子类可以定义父类中不存在的可选参数。
abstract AB
{
public function run()
{
echo 'running...';
}
abstract public function eat();
abstract public function sleep();
}
class Test extends AB
{
public function eat()
{
echo 'eating...';
}
public function sleep($time = '21:00 PM') // 可以定义父类方法中不存在的可选参数
{
echo 'sleep @ ' . $time;
}
}
单例模式
只能被实例化一次,节省内存空间
class Test
{
private static $instance = null;
private function __constrct()
{}
private function __clone()
{}
public static function getInstance()
{
if (!(self::instance instanceof self)) {
self::instance = new self();
}
return self::instance;
}
}
$test = Test::getInstance(); // 多次调用也只是实例化一次
工厂模式
Interface CacheI
{
public function set($key, $value);
public function get($key);
public function delete($key);
}
class Memcache implements CacheI
{
public function set($key, $value){}
public function get($key){}
public function delete($ke){}
}
class Redis implements CacheI
{
public function set($key, $value){}
public function get($key){}
public function delete($ke){}
}
class Cache
{
public static function factory()
{
return new Memcache(); // 这里可以是继承了CacheI接口的任何类,比如Redis
}
}
$cache = Cache::factory();
$cache->set('name', 'tom');
$cache->get('name');
$cache->delete('name');
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。