《PHP核心技术与最佳实践》读书笔记(面向对象篇)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Return_True_hang/article/details/51049091

对象

  1. php的对象是用数组模拟的,可以强制类型转换之后打印出来。print_r((array)$student); 由此可见对象是一堆数据。所以可以把一个对象存储起来,以便需要时用,也就是对象的序列化。
//序列化把内存中的对象当前状态保存到一个文件中
$str = serialize($student);
echo $str;
file_put_contents('store.txt',$str);
//需要时,反序列取出这个对象
$str = file_get_contents('store.txt');
$student = unserialize(str)
$student->say();
  1. 对象是很普通的变量,不同的是其携带了对象的属性和类的入口。
//php 源码中对变量的定义
typedef union_zvalue_value {
    long lval;/* ling value*/
    double dval;/*double value*/
    struct {
        char *val;
        int len;
    }str;
    HashTable *ht; /* hash table value */
    zend_object_value obj;
}
//对对象的定义
typedef struct_zend_object {
    zend_class_entry *ce //类的入口
    HashTable *properties; //属性组成的HashTable
    HashTable *guards;
}zend_object;

    • 类是定义一系列属性和操作的模板,而对象则把属性进行具体化,然后交给类处理。
    • 对象就是数据,对象本身不包含方法,但是对象有一个指针指向一个类,这个类可以有方法。
    • 方法描述不同属性所导致的不同表现。
    • 类和对象是不可分割的,有对象就必定有一个类与其对应。(有一种特殊情况,由标量进行强制类型转换的object,没有一个类与其对应,php中一个称为“孤儿”的stdClass类就会收留这个对象)。

魔术方法

__construct 构造方法
__destruct 析构方法
__set 外部类修改和设置内部私有属性值
__get
java 允许多个构造函数,只要保证方法签名不一样就行,而php一个类中只能允许有一个构造函数。
作用:当给对象属性赋值或者取值时,即使这个属性不存在,也可以不报错,一定程度上增强了程序的健壮性。

public function __set($name,$value) {
    echo "Setting $name to $value \r\n";
    $this->$name = $value;
}
public function __get($name) {
    if(!isset($this->$name)) {
        echo '未设置';
        $this->$name = "正在为你设置默认值";
    }
    return $this->$name;
}

同样调用一个不存在的方法,使用 __call()可以防止报错。当调用一个不可访问的方法(未定义或者不可见)时,__call()也会被调用。

public function __call($name,$argments) {
    switch(count($argments)) {
        case 2:
            echo $arguments[0]*$arguments[1],PHP_EOF;
            break;
        case 3:
            echo array_sum($arguments).PHP_EOF;
            break;
        default:
            echo '参数不对',PHP_EOF;
            break;
    }
}

在MVC中,假设一个控制器调用了一个不存在的方法,那么只要定义了__call 方法就能友好地处理这种情况。

__toString 方法,php中方法不区分大小,但实际开发注意规范。echo 打印对象体时,对象就会自动调用它所属类定义的__toString方法,格式化输出这个对象所包含的数据。输出结果可以定制。这个方法设计原型来源于java,java中也有这么一个方法,而且在java中,这个方法也是一种序列化,php自带的serialize/unserialize也是进行序列化的,但是这组函数序列化会产生一些无用信息,造成浪费。当然,也可以使用json_encode/json_decode.

其实echo本身是可以打印一个对象,而且也实现了这个接口,但是php对其做了个限制,只有实现__toString 后才允许使用。

class Account{
    public $user = 1;
    private $pwd = 2;
    public function __toString(){
        return"当前对象的用户名是{$this->user},密码是{$this->pwd}";
    }
}
$a = new Account();
echo $a;
echo PHP_EOL;
print_r($a);

java的构造方法比php好用,php由于有了__set/__get这一对魔术方法,使得动态增加对象的属性字段变得很方便,这体现了动态语言的优势,简单灵活。

继承&多态

面向对象的优势在于类的复用。继承与多态都是对类进行复用。一个是类级别的复用,一个是方法级别的复用。
- 类的组合
定义两个类,一个是person,一个是family;在family类中创建person类中的对象,把这个对象视为family类的一个属性,并调用它的方法处理问题,这种复用方式就是组合。
- 类的继承
用parent指代父类,用self指代自身、用“::”运算符调用父类的方法。如果声明类成员或方法为static,就不可以不实例化类而直接访问,同时也就不能通过一个对象访问其中的静态成员,也不能用”::”访问一个非静态方法。
- 组合和类的区别:
继承是一种“是,像”的关系,而组合是一种“需要”的关系。

耦合:耦合是一个软件结构内不同模块之间互连程度的度量,也就是不同模块之间的依赖关系
低耦合指模块和模块之间,尽可能地使模块间独立地存在,模块与模块之间的接口尽量少而简单。
- 继承破坏封装性,从语义上说,要优于继承。
- 继承是紧耦合的,继承使得子类和父类捆绑在一起,组合仅通过唯一接口和外部进行通信。
- 继承扩展复杂,继承层数的增加和子类的增加,将涉及大量的方法重写。
- 组合比继承增加了代码量

继承最大的优点是扩展简单,但是其缺点大于优点,所以
* 精心涉及专门用于被继承的类,继承树的抽象层应该比较稳定,不要超过三层
* 不是专门用于被继承的类,使用final修饰符。
* 优先考虑用组合关系提供代码的可重要行。
* 子类是一种特殊的类型,而不只是父类的一个角色。
* 子类扩展,而不是覆盖或者使父类的功能失效。
* 底层代码多用组合,顶层、业务层代码多用继承。底层用组合可以提高效率,避免臃肿。顶层代码用继承可以提高灵活性。
c++里用多继承来增强继承的灵活性,但是多重继承过于灵活,并且带来“菱形问题”。php 5.4引入Traits,思想来源于C++和Ruby里的Mixin以及Scala里的Traits。

多肽
真正的意义在于:实际开发中,只要关心一个接口或基类的编程,而不关心一个对象所属于的具体类。PHP作为一门脚本语言,自身就是多态的。php中父类和子类看做“继父”和“继子”的关系,但不存在血缘关系,子类无法向上转型为父类,从而失去多态最典型的特征。

没有更多推荐了,返回首页