面向对象三大特性:继承、封装、多态。
五大基本原则:单一职责原则、开放封闭原则(扩展开放、更改封闭)、替换原则(子类可以替换父类)、
依赖原则(上层依赖下层,接口)、接口分离原则
重载:其他语言中包含属性重载、方法重载,在C++中还有运算符重载。
在其他编程语言中,重载一般针对方法而言,满足参数类型或参数个数不一样就叫重载;
在PHP中的重载是指动态地创建类属性和方法,通过魔术方法实现。
魔术方法
以“__”开头的类方法保留为魔术方法。
__construct()、__destruct()构造方法和析构方法,
__call()、__callStatic()动态函数创建,
__get()、__set()、__isset()、__unset()动态属性获取、创建、是否存在、注销,
__wakeup()、__sleep()序列化和反序列化函数前后调用
以下代码仿照https://my.oschina.net/sallency/blog/629206
<?php
class Person
{
private $name, $age, $sex, $info;
public function __construct( $name, $age, $sex )
{
$this->name = $name;
$this->age = $age;
$this->sex = $sex;
$this->info = sprintf("prepared by construct magic functionname: %s age: %d sex: %s",
$this->name, $this->age, $this->sex);
}
public function getInfo()
{
echo $this->info . PHP_EOL;
}
/**
* serialize前调用 用于删选需要被序列化存储的成员变量
* @return array [description]
*/
public function __sleep()
{
echo __METHOD__ . PHP_EOL;
//序列化时只会存储 name age sex, info 不会被序列化
//若要序列化info,则return ['name', 'age', 'sex','info'];
return ['name', 'age', 'sex'];
}
/**
* unserialize前调用 用于预先准备对象资源
*/
public function __wakeup()
{
echo __METHOD__ . PHP_EOL;
//不设置则为construct里的info方法
$this->info = sprintf("prepared by wakeup magic function name: %s age: %d sex: %s",
$this->name, $this->age, $this->sex);
}
}
$boy = new Person( 'sallency', 25, 'male' );
//构造函数组装的 $info
$boy->getInfo();
//序列化时并不会存储 $info 属性
$temp = serialize($boy);
echo $temp . PHP_EOL;
//反序列化时会调用 __wakeup() 函数
$boy = unserialize($temp);
//__wakeup() 组装的 $info
$boy->getInfo();
其执行结果为
可在 __wakeup()、__sleep()中对序列化的内容进行选择和修改,如果没有return或者使用方法,则报错。若把__sleep
()中的return去掉,则报如下错误:
__toString()一个类被当作字符串时的处理方法,代码为PHP手册代码
<?php
// Declare a simple class
class TestClass
{
public $foo;
public function __construct($foo)
{
$this->foo = $foo;
}
public function __toString() {
return $this->foo;
}
}
$class = new TestClass('Hello');
echo $class;
//最终输出“Hello”
__invoke()当尝试以调用函数的方式调用一个对象时调用,
<?php
class CallableClass
{
function __invoke($x) {
var_dump($x);
}
}
$obj = new CallableClass;
$obj(5);
var_dump(is_callable($obj)); //检测参数是否为合法的可调用结构
//输出内容如下
int(5)
bool(true)
__set_state()调用var_export()导出类时,方法会被调用,代码为php手册代码
<?php
class A
{
public $var1;
public $var2;
public static function __set_state($an_array) // As of PHP 5.1.0
{
$obj = new A;
$obj->var1 = $an_array['var1'];
$obj->var2 = $an_array['var2'];
return $obj;
}
}
$a = new A;
$a->var1 = 5;
$a->var2 = 'foo';
eval('$b = ' . var_export($a, true) . ';'); // $b = A::__set_state(array(
// 'var1' => 5,
// 'var2' => 'foo',
// ));
var_dump($b);
//输出
object(A)#2 (2) {
["var1"]=>
int(5)
["var2"]=>
string(3) "foo"
}
echo、print、print_r、var_dump、var_export的区别:
echo:语言结构,可以不使用括号,不适用括号时可打印很多变量;
print:仅至此1个参数,echo输出速度比print快;
print_r:第二个参数为true时,会返回信息,不打印;
var_dump():会有变量的类型和长度,比print_r()显示得更详细;
var_export():返回合法的php代码。
var_export和var_dump的区别:
<?php
function returnArr(){
return ['a'=>123,'b'=>'345'];
}
var_dump(returnArr());
#输出array(2) { ["a"]=> int(123) ["b"]=> string(3) "345" }
var_export(returnArr());
#输出array ( 'a' => 123, 'b' => '345', )
__clone():当复制完成时,如果定义了 __clone() 方法,则新创建的对象(复制生成的对象)中的 __clone() 方法会被调用,可用于修改属性的值 (不太看得懂代码,存疑),
<?php
class SubObject
{
static $instances = 0;
public $instance;
public function __construct() {
$this->instance = ++self::$instances;
}
public function __clone() {
$this->instance = ++self::$instances;
}
}
class MyCloneable
{
public $object1;
public $object2;
function __clone()
{
// 强制复制一份this->object, 否则仍然指向同一个对象
$this->object1 = clone $this->object1;
}
}
$obj = new MyCloneable();
$obj->object1 = new SubObject();
$obj->object2 = new SubObject();
$obj2 = clone $obj;
print("Original Object:\n");
print_r($obj);
print("Cloned Object:\n");
print_r($obj2);
//输出
Original Object:
MyCloneable Object
(
[object1] => SubObject Object
(
[instance] => 1
)
[object2] => SubObject Object
(
[instance] => 2
)
)
Cloned Object:
MyCloneable Object
(
[object1] => SubObject Object
(
[instance] => 3
)
[object2] => SubObject Object
(
[instance] => 2
)
)