近来参加了几场PHP工程师的面试,但是笔试题答得都不理想,回来总结了一下失败的原因,是没看PHP手册。几家公司的PHP基础面试题都可以在PHP手册上找到。哎,现在才知道最好的面试宝典是PHP手册。 下面是一些PHP面向对象基础知识的摘录,摘录内容来自PHP5.1手册。 1.类的变量成员叫做“属性”,或者叫“字段”、“特征”,在本文档统一称为“属性”。 2.属性中的变量可以初始化,但是初始化的值必须是常数,这里的常数是指php脚本在编译阶段时就为常数,而不是 在编译阶段之后在运行阶段运算出的常数。 3.在类的成员方法里面,可以通过$this->property(property是属性名字)这种方式来访问类的属性、 方法,但是 要访问类的静态属性或者在静态方法里面却不能使用,而是使用self::$property。 4.在类的非静态方法里面可以使用伪变量$this,这个伪变量是调用该方法的实例化对象引用 5.常量的值必须是一个定值,不允许修改,且不能是变量,类属性或其它操作(如函数调用)的结果。 <?php class MyClass { const constant = 'constant value'; function showConstant() { echo self::constant . "\n"; } } echo MyClass::constant . "\n"; $n=new MyClass(); $n->showConstant(); ?> 6.构造函数的类会在每次创建对象时先调用此方法,所以非常适合在使用对象之前做一些初始化工作。 如果子类中定义了构造函数则不会暗中调用其父类的构造函数。要执行父类的构造函数,需要在子类的构造函数中 调用 parent::__construct()。 7.析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行。 父类的析构函数不会被引擎暗中调用。要执行父类的析构函数,必须在子类的析构函数体中显式调用 parent::__destruct()。 析构函数在脚本关闭时调用,此时所有的头信息已经发出。 试图在析构函数中抛出一个异常会导致致命错误。 8.当扩展一个类,子类就会继承父类的所有公有和保护方法。但是子类的方法会覆盖父类的方法。 9.范围解析操作符(::),可以用于访问静态成员、方法和常量 当在类的外部访问这些静态成员、方法和常量时,必须使用类的名字。 self 和 parent这两个特殊的关键字是用于在类的内部对成员或方法进行访问的。 10.当一个子类覆盖其父类中的方法时,PHP 不会再执行父类中已被覆盖的方法,直到子类中调用这些方法为止。这 种机制也作用于 构造函数和析构函数、重载 及 魔术 函数。 11.静态变量和方法 声明类成员或方法为static,就可以不实例化类而直接访问。不能通过一个对象来访问其中的静态成员(静态方法 除外)。 由于静态方法不需要通过对象即可调用,所以伪变量$this在静态方法中不可用。 静态属性不可以由对象通过->操作符来访问。 用::方式调用一个非静态方法会导致一个E_STRICT级别的错误。 就像其它所有的PHP静态变量一样,静态属性只能被初始化为一个字符值或一个常量,不能使用表达式。 所以你可 以把静态属性初始化为整型或数组,但不能指向另一个变量或函数返回值,也不能指向一个对象。 12.如果没有指定“可见性”,属性和方法默认为public。 13.抽象类 抽象类不能直接被实例化,你必须先继承该抽象类,然后再实例化子类。抽象类中 至少要包含一个抽象方法。如果 类方法被声明为抽象的,那么其中就不能包括具体的功能实现。 继承一个抽象类的时候,子类必须实现抽象类中的所有抽象方法;另外,这些方法的可见性 必须和抽象类中一样( 或者更为宽松)。如果抽象类中某个抽象方法被声明为protected,那么子类中实现的方法就应该声明为protected 或者public,而不 能定义为private。 应用示例: abstract class AbstractClass { // 强制要求子类定义这些方法 abstract protected function getValue(); abstract protected function prefixValue($prefix); // 普通方法(非抽象方法) public function printOut() { print $this->getValue() . "\n"; } } class ConcreteClass1 extends AbstractClass { protected function getValue() { return "ConcreteClass1"; } public function prefixValue($prefix) { return "{$prefix}ConcreteClass1"; } } 14.使用接口(interface),你可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容。 我们可以通过interface来定义一个接口,就像定义一个标准的类一样,但其中定义所有的方法都是空的。 接口中定义的所有方法都必须是public,这是接口的特性。 要实现一个接口,可以使用implements操作符。类中必须实现接口中定义的所有方法,否则 会报一个fatal错误。 如果要实现多个接口,可以用逗号来分隔多个接口的名称。 实现多个接口时,接口中的方法不能有重名。 接口也可以继承,通过使用extends操作符。 接口中也可以定义常量。接口常量和类常量的使用完全相同。 它们都是定值,不能被子类或子接口修改。 应用示例: //接口定义 interface iTemplate { public function setVariable($name, $var); public function getHtml($template); } //使用接口 class Template implements iTemplate { private $vars = array(); public function setVariable($name, $var) { $this->vars[$name] = $var; } public function getHtml($template) { foreach($this->vars as $name => $value) { $template = str_replace('{' . $name . '}', $value, $template); } return $template; } } 15.PHP5提供了一种迭代(iteration)对象的功能,就像使用数组那样,可以通过foreach来遍历对象中的属性。 默认情况下,在外部迭代只能得到外部可见的属性的值。 应用示例: <?php class MyClass { public $var1 = 'value 1'; public $var2 = 'value 2'; public $var3 = 'value 3'; protected $protected = 'protected var'; private $private = 'private var'; function iterateVisible() { echo "MyClass::iterateVisible:\n"; foreach($this as $key => $value) { print "$key => $value\n"; } } } $class = new MyClass(); foreach($class as $key => $value) { print "$key => $value\n"; } echo "\n";
$class->iterateVisible(); ?> 16.设计模式 工厂模式(Factory)允许你在代码执行时实例化对象。它之所以被称为工厂模式是因为它负责“生产”对象。工厂 方法的参数是 你要生成的对象对应的类名称。 单例模式(Singleton)用于为一个类生成一个唯一的对象。最常用的地方是数据库连接。 使用单例模式生成一个 对象后,该对象可以被其它众多对象所使用。 应用示例: <?php class Example { // 保存类实例在此属性中 private static $instance; // 构造方法声明为private,防止直接创建对象 private function __construct() { echo 'I am constructed'; } // singleton 方法 public static function singleton() { if (!isset(self::$instance)) { $c = __CLASS__; self::$instance = new $c; } return self::$instance; } // Example类中的普通方法 public function bark() { echo 'Woof!'; } // 阻止用户复制对象实例 public function __clone() { trigger_error('Clone is not allowed.', E_USER_ERROR); } } ?>
这样我们可以得到一个独一无二的Example类的对象。
<?php // 这个写法会出错,因为构造方法被声明为private $test = new Example; // 下面将得到Example类的单例对象 $test = Example::singleton(); $test->bark(); // 复制对象将导致一个E_USER_ERROR. $test_clone = clone $test; ?> 17.PHP 5 新增了一个 final 关键字。如果父类中的方法被声明为final,则子类无法覆盖该方法; 如果一个类被 声明为final,则不能被继承。 18.对象复制可以通过clone关键字来完成(如果对象中存在__clone()方法,会先被调用)。对象中的 __clone() 方法不能直接调用。 $copy_of_object = clone $object; 当对象被复制后,PHP5会对对象的所有属性执行一个“浅复制”(shallow copy)。所有的属性中的引用 仍然不 变,指向原来的变量。如果定义了__clone()方法,则新创建的对象(复制生成的对象)中的__clone()方法会被调 用, 可用于修改属性的值(如果有必要的话)。 19.对象比较 当使用对比操作符(==)比较两个对象变量时,比较的原则是:如果两个对象的属性和属性值 都相等,而且两个对象 是同一个类的实例,那么这两个对象变量相等。www.2cto.com 而如果使用全等操作符(===),这两个对象变量一定要指向某个类的同一个实例(即同一个对象)。 20.对象和引用 php的引用是别名,就是两个不同的变量名字指向相同的内容。在php5,一个对象变量已经不再保存整个对象的值。 只是保存一个标识符来访问真正的对象内容。 当对象作为参数传递,作为结果返回,或者赋值给另外一个变量,另 外一个变量跟原来的不是引用的关系,只是他们都保存着同一个标识符的拷贝,这个标识符指向同一个对象的真正 内容
|