《PHP核心技术与最佳实践》学习笔记①

一、面向对象的思想和概念

面向对象的理解

  • 面向对象和面向过程的对比

面向对象编程语言(C++、Java、PHP)和面向过程编程语言(C)的区别。由于只熟悉面向对象语言,只是了解面向对象语言的封装、继承、多态的特性,并不是很熟悉面向过程语言(C)可能没办法更好的体会面向对象的这几个特性。
面向对象只是编程语言的特定,代码能不能体现面向对象的特点,主要是靠代码的设计和编码。

  • 类和对象的关系

类是属性和方法的集合,而对象则是属性的集合。
打印对象时只有属性,没有方法。
类的区分应该是靠属性来区分,即不同的类应该是由不同的属性构成。
对象是类的实例化结果,不同的对象有不同的属性,但是共享了类中的方法。

  • 对象的本质

对象在PHP底层是如何保存的?
对象在PHP底层也是一种变量,和字符串,数组类似,也可以理解为是特殊的变量。都是以结构体的方式来保存的。

#zend/zend_types.h
typedef union_zend_value{
    zend_long lval;     /* long value */
    double dval;        /* double value */
    zend_refcounted *counted;
    zend_string *str;
    zend_array *arr;
    zend_object *obj;   //用于对象
    zend_resource *res;
    zend_reference *ref;
    zend ast_ref *ast;  //用于常量表达式
    zval *zv;
    void *ptr;
    zend_class_entry *ce;
    zend_function *func;
    struct{
        uint32_t w1;
        uint32_t w2;
    } ww;
} zend_value;

下图是PHP源码里对变量的定义,我们看到对象也是其中的一种。zend_object
我们看对象在PHP源码里是以何种结构体来定义的:

#zend/zend_types.h
struct_zend_object{
    zend_refcounted_h gc;
    uint32_t      handle;   // TODO:may be removed???
    zend_class_entry *ce;       //这里就是入口
    const zend object_handlers *handlers;
    HashTable *properties;
    zval properties_table[1];
}

ce是存储该对象的类结构,在对象初始化保存了类的入口,相当于类指针的作用。

  • 对象与数组

既然对象和数组在底层是一样的结构,那我们就可以来比较下这两者有什么区别。
从PHP代码来看,两者对我们而言更多的可能是取值的方式的区别,下面我们通过序列化来比较下。

//数组序列化
$student_arr = array('name'=>'Tom','gender'=>'male');

echo serialize($student_arr);
echo "\n";

//对象序列化
class person{
    public $name;
    public $gender;

    public function say(){
        echo $this->name," is ",$this->gender;
        echo "\n";
    }
}
$student = new person();
$student->name = 'Tom';
$student->gender = 'male';
$student->say();
echo serialize($student);
echo "\n";

输出结果

a:2:{s:4:"name";s:3:"Tom";s:6:"gender";s:4:"male";}
Tom is male
O:6:"person":2:{s:4:"name";s:3:"Tom";s:6:"gender";s:4:"male";}

我们看到,数组和对象序列化后的结果基本相同,唯一的区别就是对象前会有类的名称,这个名称可以对应到源码结构中的ce指针,就是类的入口。就是说,通过这个指针可以找到对象是所属哪个类的。

魔术方法

  • __set
    给一个不存在的属性赋值时被调用
  • __get
    获取一个不存在的属性值,和获取无权限的属性时(例如类外部调用private和protected的属性)被调用
  • __call
    调用不存在的方法时触发
  • __callStatic
    调用不存在的静态方法时触发
  • __toString
    echo一个对象时触发
  • __debugInfo
    打印所需调试信息

命名空间和自动加载

自动加载函数 spl_autoload_register

继承和多态

类的继承与组合

  • 继承破坏封装性
  • 继承是紧耦合的
  • 继承扩展复杂
    组合相比于继承,更易于扩展,更灵活,耦合度更低,但是组合的代码量更多。

组合可以理解为include/require其他类

PHP中如果既要组合的灵活,又要继承的简洁,那就需要用到trait这个语法
详细介绍点这里

多态

多态更多的是针对强类型语言来说的。

多态的定义:

同一类的对象收到相同消息时,会得到不同的结果

简单归纳就是同一类型,不同结果
重点就在同一类型上,对于弱类型语言,所有的对象都可以理解为同一种类型,所以,从某种意义上说,弱类型语言本身就是多态,但是在强类型语言中,这不是多态。
但是PHP中有一个接口的概念,通过接口可以实现符合同一类型,不同结果的多态。

working();
}

$a = new teacher;

$b = new coder;
$c = new farmer;
doprint($a);
doprint($b);
doprint($c);

以上代码输出结果

teaching
coding
PHP Catchable fatal error:  Argument 1 passed to doprint() must implement interface employee, instance of farmer given, called in /home/hupengchen/php_study/1-10.php on line 33 and defined in /home/hupengchen/php_study/1-10.php on line 24

我们可以看到当限定doprint函数的参数是一个接口类型变量时,就能很好的理解多态。farmer类不是接口类型,所以会报错。

面向接口编程

PHP中接口并不是很严格,PHP里只关心是否实现接口里的方法,而并不关心接口语义是否正确。

如下代码所示:

#interface.php

fly();      //mobile接口是没有这个方法的
        }
}

$obj = new machine();

$obj->demo(new plain());
$obj->demo(new car());

输出结果

this is plain fly!
PHP Fatal error:  Call to undefined method car::fly() in /home/hupengchen/php_study/interface.php on line 23

通过上面代码,我们可以看到在PHP中,可以通过接口类型去实现一个接口中并不存在的方法。而在Java中,当你定义了一个接口类型的参数,但又要实现一个接口中不存在的方法时,会报错,因为这并不符合接口的规范。
所以,我们可以认为接口是一套规范,当我们在PHP中用的时候,也尽量是在需要定义一套规范的场景中使用。

PHP内置的一个Iterator迭代器接口,通过这个接口可以使对象使用foreach结构。

反射

反射就是可以通过对象找到类(包括类的属性,方法,文件名等一切内容)

用法:
使用ReflectionObject来实现反射

$reflect = new ReflectionObject($student);
//获取对象属性列表
$props = $reflect->getProperties();
foreach($props as $prop){
    $prop->getName();
}
//获取对象方法列表
$m = $reflect->getMethods();
foreach($m as $prop){
    $prop->getName();
}

异常和错误

其他语言中,异常和错误是分开处理的,但是在PHP中遇到自身任何错误都是触发一个错误。
PHP中需要throw手动抛出异常,才能捕获异常。
PHP的错误机制
php7对异常机制的改进:
php7实现了一个全局的Throwable接口,原来的Exception和部分error实现了这个接口。以接口的方式定义了异常的继承结构。
我们以上一节interface.php中的代码来验证下PHP7中和PHP5中对Throwable的改进。

#测试Exception

try{
        $obj->demo(new car());
}catch(Exception $e){
        echo 'catch exception!'.PHP_EOL;
        echo $e->getMessage().PHP_EOL;
}

//php5运行
[root@localhost php_study]# php interface.php 
this is plain fly!
PHP Fatal error:  Call to undefined method car::fly() in /home/hupengchen/php_study/interface.php on line 23

//php7运行
[root@localhost php_study]# php72 interface.php 
this is plain fly!
PHP Fatal error:  Uncaught Error: Call to undefined method car::fly() in /home/hupengchen/php_study/interface.php:23
Stack trace:
#0 /home/hupengchen/php_study/interface.php(30): machine->demo(Object(car))
#1 {main}
  thrown in /home/hupengchen/php_study/interface.php on line 23

Fatal error: Uncaught Error: Call to undefined method car::fly() in /home/hupengchen/php_study/interface.php:23
Stack trace:
#0 /home/hupengchen/php_study/interface.php(30): machine->demo(Object(car))
#1 {main}
  thrown in /home/hupengchen/php_study/interface.php on line 23

我们看到php7虽然对于PHP5多了异常的提示,但是也是作为错误抛出。下面我们来看Throwable

#测试Throwable

try{
        $obj->demo(new car());
}catch(Throwable $e){
        echo 'catch exception!'.PHP_EOL;
        echo $e->getMessage().PHP_EOL;
}

//php5运行
[root@localhost php_study]# php interface.php 
this is plain fly!
PHP Fatal error:  Call to undefined method car::fly() in /home/hupengchen/php_study/interface.php on line 23

//php7运行
[root@localhost php_study]# php72 interface.php 
this is plain fly!
catch exception!
Call to undefined method car::fly()

我们看到PHP7中用Throwable已经可以将异常捕获到了。

小结

我们看到PHP虽然是面向对象语言,但是毕竟是弱类型的动态脚本语言,相对于Java和C++等强类型的语言,在面向对象的特性方面(命名空间,多态,接口,异常处理等),并不是很严谨。但是这正是PHP的特点——灵活。使得PHP成为全球web应用使用最多的编程语言。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇