php核心技术与最佳时间 --- oop基础

<?php
/**
 * Created by PhpStorm.
 * User: cl
 * Date: 2019/8/12
 * Time: 7:08
 */
/*oop*/
class Person{
    public $name;
    public $gender;
    public function say(){
        echo $this->name,'is',$this->gender;
    }
}

$student = new Person();
$student->name = "CL";
$student->gender = "MAN";
$student->say();
// CLisMAN
var_dump((array)$student);
// array(2) { ["name"]=> string(2) "CL" ["gender"]=> string(3) "MAN" }
// 对象由属性组成,一个对象的属性是它区别于另一个对象的关键所在。由于php的对象使用数组来模拟的
// 因此我们把对象转成数组,就能看见这个对象所拥有的属性了。
// 到这里,可以直观的认识到,对象就是一堆数据。既然如此,可以把一个对象存储起来,以便需要时用,这就是对象的序列化。
$str = serialize($student);
var_dump($str);
// string(60) "O:6:"Person":2:{s:4:"name";s:2:"CL";s:6:"gender";s:3:"MAN";}"
// 在需要时,可以反序列化取出这个对象
var_dump(unserialize($str));
// object(Person)#2 (2) { ["name"]=> string(2) "CL" ["gender"]=> string(3) "MAN" }
// 可以看到,对象序列化后,存储的只是对象的属性。类是由属性和方法组成的,而对象则是属性的集合,由同一个类生成的不同对象,
// 拥有各自不同的属性,但共享了类的代码空间中方法区域的代码。

/*对象与数组*/
// 数组是由键值对数据组成,数组的键值对和对象的属性/属性值对十分相似。对象序列化后和数组序列化后的结果是
// 惊人的相似
$student_arr = ['name' => 'CL' , 'gender' => 'MAN'];
var_dump(serialize($student_arr));
//  string(49) "a:2:{s:4:"name";s:2:"CL";s:6:"gender";s:3:"MAN";}"
// 区别在于 : 对象中还包含指针,指向了它所属的类。

/* 对象与类*/
// 如果对象中还包含对象,那么序列化后会是什么样子呢?
class Family{
    public $people;
    public $location;
    public function __construct ($p,$loc){
        $this->people = $p;
        $this->location = $loc;
    }
/*    public function __destruct(){
        var_dump('魔术方法之析构方法');
    }*/
}
$tom = new Family($student,"peking");
var_dump(serialize($tom));
// string(118) "O:6:"Family":2:{s:6:"people";O:6:"Person":2:{s:4:"name";s:2:"CL";s:6:"gender";s:3:"MAN";}s:8:"location";s:6:"peking";}"
/* 可以看出,序列化后的对象会附带所属类型,这个类名保证此对象在执行类的方法(也是自己所能执行的方法)时,
    能够正确地找到方法所在的代码空间(即对象所拥有的方法存储在类里)。另外,当一个对象的实例变量引用其他对象时,序列化对象
    也会对引用对象进行序列化
    由此可以分析二者的关系 :
    类是定义一系列属性和操作的模板,而对象则是把属性进行具体化,然后交给类处理
    对象就是数据,对象本身包含方法。但是对象有一个”指针“指向一个类,这个类里可以有方法。
    方法描述不同属性导致的不同表现
    类和对象是不可分割的,有对象就必定有一个类与其对应,否则这个对象也就成了没有亲人的孩子(但有一个特殊的情况,就是
    由标量进行强制类型转换的object,没有一个类与它对应。此时,PHP中一个称为”孤儿“的stdClass类就会收留这个对象)
    可以看出,在面向对象层面,js和php区别还是很大的。
*/

/*魔术方法*/
/*
 * 魔术方法是以两个下划线开头,具有特殊作用的一些方法,可以看作是PHP的语法糖
 * 语法糖是指那些没有给计算机添加新功能,而对人类来说更甜蜜的语法
 * Family类的__construct方法就是一个标准的魔术方法。这个魔术方法又称构造方法。具有构造方法的类会每次创建对象时
 * 先调用此方法,所以非常适合在使用对象之前做一些初始化工作,如:给属性赋值,连接数据库等
 * 有构造方法就有析构方法,即destruct方法,这个方法会在某个对象的所以引用都被删除,或者当对象被显式销毁时执行。
 * 这两个方法是最常见也是最有用的魔术方法
 */
/*魔术方法之set 和 get*/
class Account{
    private $user = 1;
    private $pwd = 2;

    public function __get($name){
        echo '请求'.$name;
    }
    public function __set($name,$val){
        echo "请求设置".$name."为".$val;
    }


    public function __call($name ,$arguments){
        // $name : 要调用的方法名称
        // $arguments : 数组,包含着要传递给方法的参数
        var_dump($name);
        var_dump($arguments);
    }
    public static function __callStatic($name ,$arguments){
        var_dump($name);
        var_dump($arguments);
    }
    public function __toString()
    {
        return '任意字符串';
    }

}
$a = new Account();
$a->user; // 如果没有 __get 魔术方法则会报错,大致意思是不能访问对象的私有属性
// 请求user
$a->name = '123'; // 因为对象没有name属性,所以会触发 __set 魔术方法
// 请求设置name为123
/*
 * 可以直观的看到,若类中定义了set 和 get这一对魔术方法,那么当给对象属性赋值或取值时,即使
 * 这个属性不存在,也不会报错,一定程度上增强了程序的健壮性
 */
// 那么,如果防止调用一个不可访问的方法(如未定义,或者不可见)时,call()会被调用。
$a->demo('1','2');
// "demo"
// array(2) { [0]=> string(1) "1" [1]=> string(1) "2" }
// 当调用的静态方法不存在或权限不足时,callStatic() 会被调用
Account::demo();
// "demo"
// array(0) { }

// 当然,使用魔术方法"防止调用不存在的方法而报错",并不是魔术方法的本意。实际上,魔术方法使方法的动态创建变为可能。
// 这在MVC等框架设计中是很有用的语法。可以通过一段代码使用callStatic这一魔术方法进行方法的动态创建和延迟绑定

// toString方法
echo $a; //任意字符串
// 比如打印一个对象时,看看这个对象都有哪些属性,其值是什么,如果定义了toString方法,就能在测试时,echo打印对象体
// 对象会自动调用它所属类定义的toString方法,格式化输出这个对象所包含的数据。如果没有这个方法,那么echo一个对对象将报错

猜你喜欢

转载自www.cnblogs.com/cl94/p/11343616.html