1.自动加载
autoload机制可以使得PHP程序有可能在使用类时才自动包含类文件,而不是一开始就将所有的类文件include进来,这种机制也称为lazy loading。通常PHP5在使用一个类时,假如发现这个类没有加载,就会自动运行__autoload()函数,在这个函数中我们可以加载需要使用的类。
使用autoload机制时,很多人的第一反应就是使用autoload会降低系统效率,甚至有人干脆提议为了效率不要使用autoload。在了解了autoload实现的原理后,我们知道autoload机制本身并不是影响系统效率的原因,甚至它还有可能进步系统效率,由于它不会将不需要的类加载到系统中()。
很多人都有一个使用autoload会降低系统效率的印象是因为。。实际上,影响autoload机制效率本身恰正是用户设计的自动加载函数。假如它不能高效的将类名与实际的磁盘文件(留意,这里指实际的磁盘文件,而不仅仅是文件名)对应起来,系统将不得不做大量的文件是否存在(需要在每个include path中包含的路径中往寻找)的判定,而判定文件是否存在需要做磁盘I/O操纵,众所周知磁盘I/O操纵的效率很低,因此这才是使得autoload机制效率降低的罪魁罪魁!
因此,在系统设计时,需要定义一套清楚的将类名与实际磁盘文件映射的机制。这个规则越简单越明确,autoload机制的效率就越高。
结论:autoload机制并不是自然的效率低下,只有滥用autoload,设计不好的自动装载函数才会导致其效率的降低。
本例:尝试分别从 MyClass1.php 和 MyClass2.php 文件中加载 MyClass1 和 MyClass2 类。
<?php
function __autoload($class_name) {
require_once $class_name . '.php';
}
$obj = new MyClass1();
$obj2 = new MyClass2();
?>
2.克隆
(1)克隆是将对象在堆中复制了一份( $clone_apple = clone $apple;),
(2)直接用等号复制是对象的应用在栈中复制了一份( $clone_apple = $apple;),
(3)对象加上&赋值是将对象的应用起了一个别名,不会在栈中开辟空间
( $clone_apple = &$apple;)
<?php
header("Content-type: text/html;charset=utf-8");
class Fruit {
private $name = "水果";
private $color = "颜色";
public function setName($name){
$this->name = $name;
}
public function setColor($color){
$this->color = $color;
}
function showColor(){
return $this->color.'的'.$this->name."<br />";
}
function __destruct(){
echo "被吃掉了(对象被回收) <br />";
}
}
$apple = new Fruit();
$apple->setName("大苹果");
$apple->setColor("红色");
echo $apple->showColor();
$clone_apple =&$apple; 栈中一个引用,堆中一个对象
//$clone_apple =$apple; 栈中两个引用,堆中一个对象
//$clone_apple = clone $apple; 栈中两个引用,堆中两个对象
$clone_apple->setName("小苹果");
$clone_apple->setColor("青色");
echo $clone_apple->showColor();
echo $apple->showColor();
?>
3.变量
<?php
$a = 1; /* global scope */
function Test()
{echo $a; /* reference to local scope variable */
}
Test();
?>
这个脚本不会有任何输出
Example #1 使用 global
<?php
$a = 1;
$b = 2;
function Sum()
{ global $a, $b;
$b = $a + $b;
}
Sum();
echo $b;
?>
以上脚本的输出将是"3"。
Example #2 使用 $GLOBALS 替代 global
<?php
$a = 1;
$b = 2;
function Sum()
{$GLOBALS['b'] = $GLOBALS['a'] + $GLOBALS['b'];
}
Sum();
echo $b;
?>
$GLOBALS 是一个关联数组,每一个变量为一个元素,键名对应变量名,值对应变量的内容。
<?php
$a = 'hello';
$$a = 'world';
echo "$a ${$a}";
echo "$a $hello";
?>
它们都会输出:hello world
要将可变变量用于数组,必须解决一个模棱两可的问题。这就是当写下 $$a[1] 时,解析器需要知道是想要 $a[1] 作为一个变量呢,还是想要 $$a 作为一个变量并取出该变量中索引为 [1] 的值。解决此问题的语法是,对第一种情况用 ${$a[1]},对第二种情况用 ${$a}[1]。
Example #1 可变属性示例
<?php
class foo {
var $bar = 'I am bar.';
var $arr = array('I am A.', 'I am B.', 'I am C.');
var $r = 'I am r.';
}
$foo = new foo();
$bar = 'bar';
$baz = array('foo', 'bar', 'baz', 'quux');
echo $foo->$bar . "
";
echo $foo->$baz[1] . "
";
$start = 'b';
$end = 'ar';
echo $foo->{$start . $end} . "
";
$arr = 'arr';
echo $foo->$arr[1] . "
";
echo $foo->{$arr}[1] . "
";
?>
以上例程会输出:
I am bar.
I am bar.
I am bar.
I am r.
I am B.
4.常量
- 常量前面没有美元符号($);
- 常量只能用 define() 函数定义,而不能通过赋值语句;
- 常量可以不用理会变量的作用域而在任何地方定义和访问;
- 常量一旦定义就不能被重新定义或者取消定义;
- 常量的值只能是标量
常量只能包含标量数据(boolean,integer,float 和 string)。
5.构造函数和析构函数
Php中父类中的构造函数需要子类中显示调用,否则子类只进行继承实例化,是不能调用父类的构造方法的,除非子类中没有定义构造函数。
要执行父类的析构函数,必须在子类的析构函数体中显式调用 parent::__destruct()。此外也和构造函数一样,子类如果自己没有定义析构函数则会继承父类的。