PHP高级特性


面向对象基础回顾

什么是对象?什么是类?两者有什么区别和联系?

类是对一类事物描述,是抽象的、概念上的定义;
对象是实际存在的该类事物的每个个体,因而也称实例(instance)。在计算机中,可以理解为,在内存中创建了实实在在存在的一个内存区域存储着这个对象。
创建对象的过程称为创建对象,也称为实例化。

什么是继承?PHP支持怎样的继承?

继承(Inheritance)是面向对象软件技术当中的一个概念。继承可以使得子类别具有父类别的各种属性和方法,而不需要再次编写相同的代码。

一个扩充类总是依赖一个单独的基类,也就是说,不支持多继承。使用关键字“extends”来扩展一个类。

什么是重写(overriding)?PHP是否支持重载(overloading)?

Java 重写(Override)与重载(Overload)

重写是子类对父类的允许访问的方法的实现过程进行重新编写!返回值和形参都不能改变。即外壳不变,核心重写!

重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型呢?可以相同也可以不同。

什么是静态方法?什么情况下适合使用静态方法?

静态方法只要定义了类,不必建立类的实例就可使用

全部静态意味着牺牲了OOP的三个特性,也就意味着放弃了封装、集成、多态。另外,由于没有统一编码习惯和约定,很多东西不做抽象,不做单一入口,代码本身的复用以及维护都是个问题。写多了这种代码,估计工程师本身的成就感都是个问题。 个人理解下面这几种情景下使用static关键字会比较合适:\

什么是类常量?什么情况下应该使用类常量?

可以把在类中始终保持不变的值定义为常量。

常量的值必须是一个定值,不能是变量,类属性,数学运算的结果或函数调用。

什么是抽象类?什么是接口?分别适用于何种场景?

定义为抽象的类不能被实例化。任何一个类,如果它里面至少有一个方法是被声明为抽象的,那么这个类就必须被声明为抽象的。被定义为抽象的方法只是声明了其调用方式(参数),不能定义其具体的功能实现。

使用接口(interface),可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容。接口是通过 interface 关键字来定义的,就像定义一个标准的类一样,但其中定义所有的方法都是空的。接口中定义的所有方法都必须是公有,这是接口的特性。

抽象类还是接口


异常处理

程序中运行时出现的问题, 该怎样处理?

什么是异常?

异常处理,是编程语言或计算机硬件里的一种机制,用于处理软件或信息系统中出现的异常状况(即超出程序正常执行流程的某些特殊条件)。

怎么样产生一个异常?怎样处理产生的异常?

function inverse($x) {
    if (!$x) {
        throw new Exception('Division by zero.');
    }
    else return 1/$x;
}

try {
    echo inverse(5) . "\n";
    echo inverse(0) . "\n";
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
}

怎样自定义异常?

class MyException extends Exception { }

try\catch\finally是怎样协同工作的?

PHP的error, warning, notice等类型的错误,怎样通过抛出异常的方式处理?

trigger_error — 产生一个用户级别的 error/warning/notice 信息

怎样捕捉PHP中的致命错误?

set_error_handler("customError");


Traits

Traits是什么?

Traits 是一种为类似 PHP 的单继承语言而准备的代码复用机制。Trait 为了减少单继承语言的限制,使开发人员能够自由地在不同层次结构内独立的类中复用方法集。Traits 和类组合的语义是定义了一种方式来减少复杂性,避免传统多继承和混入类(Mixin)相关的典型问题。

什么场景下适合使用Trait?

PHP使用单一继承模型。虽然这种模型足够应付大部分用例场景,但有时用户也需要将一些通用样板代码放置其他无关联的类中。

怎样使用Trait?

trait PropertiesTrait {
    public $same = true;
    public $different = false;
}

class PropertiesExample {
    use PropertiesTrait;
    public $same = true; // Strict Standards
    public $different = true; // 致命错误
}

trait Hello {
    public function sayHello() {
        echo 'Hello ';
    }
}

trait World {
    public function sayWorld() {
        echo 'World!';
    }
}

trait HelloWorld {
    use Hello, World;
}

class MyHelloWorld {
    use HelloWorld;
}

预订义接口

PHP中有哪些预订义接口?它们可实现什么功能?

怎样使用PHP的预订义接口?

Traversable是什么?Iterator和IteratorAggregate是什么?

Traversable 无法被单独实现的基本抽象接口。相反它必须由 IteratorAggregate 或 Iterator 接口实现。

Iterator extends Traversable {
/* 方法 */
abstract public mixed current ( void )
abstract public scalar key ( void )
abstract public void next ( void )
abstract public void rewind ( void )
abstract public boolean valid ( void )
}

IteratorAggregate extends Traversable {
/* 方法 */
abstract public Traversable getIterator ( void )
}

foreach是否只能用于遍历数组?

怎样高效便捷地读取超大的文本文件?

class FileIterator implements Iterator

怎样通过数组的方式调用自定义类中的数据?

ArrayAccess(数组式访问)

yield是什么东西?它和Generator类,Traversable类有什么联系?

Generators provide an easy way to implement simple iterators without the overhead or complexity of implementing a class that implements the Iterator interface.

function xrange($start, $limit, $step = 1) {
    for ($i = $start; $i <= $limit; $i += $step) {
        yield $i;
    }
}

echo 'Single digit odd numbers: ';

/* 注意保存在内存中的数组绝不会被创建或返回 */ 
foreach (xrange(1, 9, 2) as $number) {
    echo "$number ";
}

什么是回调函数?怎样创建回调函数?

call_user_func()和call_user_func_array()

怎么样调用匿名函数?怎样在匿名函数中使用外部变量?

匿名函数(Anonymous functions),也叫闭包函数(closures),允许 临时创建一个没有指定名称的函数。最经常用作回调函数(callback)参数的值。当然,也有其它应用的情况。

$greet = function($name)
{
    printf("Hello %s\r\n", $name);
};

$greet('World');
$greet('PHP');

// 继承 $message
$example = function () use ($message) {
    var_dump($message);
};

PHP的魔术方法和魔术常量

什么是魔术方法?什么是魔术常量?

__construct(), __destruct(), __call(), __callStatic(), __get(), __set(), __isset(), __unset(), __sleep(), __wakeup(), __toString(), __invoke(), __set_state(), __clone() 和 __debugInfo() 等方法在 PHP 中被称为”魔术方法”(Magic methods)

PHP中有哪些魔术方法?

__construct(), __destruct(), __call(), __callStatic(), __get(), __set(), __isset(), __unset(), __sleep(), __wakeup(), __toString(), __invoke(), __set_state(), __clone() 和 __debugInfo() 等方法在 PHP 中被称为”魔术方法”(Magic methods)

调用类中不存在的方法会发生什么?

在对象中调用一个不可访问方法时,__call() 会被调用。用静态方式中调用一个不可访问方法时,__callStatic() 会被调用。

怎样避免一个类被实例化?

private

单例模式

类中的方法能否以类属性的方式调用?


命名空间与自动加载

什么是命名空间?怎样定义命名空间?

在PHP中,命名空间用来解决在编写类库或应用程序时创建可重用的代码如类或函数时碰到的两类问题

命名空间有什么作用?

命名空间用来解决在编写类库或应用程序时创建可重用的代码如类或函数时碰到的两类问

同一个文件内能否定义多个命名空间?

namespace MyProject;

const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */  }

namespace AnotherProject;

const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */  }

namespace MyProject {

const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */  }
}

namespace AnotherProject {

const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */  }
}

什么是非限定名称?什么是相对限定名称?什么是完全限定名称?

PHP 命名空间中的元素使用同样的原理。例如,类名可以通过三种方式引用:

定义了命名空间后,怎样调用PHP内置的函数?

怎样在一个命名空间中使用另一个命名空间下的类?

use My\Full\Classname as Another;
new \My\Full\Classname();

命名空间和文件目录有关系吗?

在文件系统中访问一个文件有三种方式:

怎样实现类的自动加载?


反射

什么是反射?

在计算机科学中,反射是指计算机程序在运行时(Run time)可以访问、检测和修改它本身状态或行为的一种能力。

通过反射可以了解哪些信息?

某个类中所有的方法、属性、注释、方法参数等

什么时候使用类函数?什么时候使用反射?

反射使用场景: 自动加载插件,自动生成文档,甚至可用来扩充PHP语言。


参考

PHP在Web开发中static的使用场景
魔术方法,延迟绑定及静态成员
后期静态绑定
PHP的新特性finally
PHP 5.4弃Register Globals增Traits
PHP5.4的新特性
PHP如何快速读取大文件
深入理解PHP之匿名函数
匿名函数及闭包\

Yan Peipan 22 January 2015